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

Commit e3c526f4 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio
Browse files

Fix Paint Shader copy

- Paint.setClassVariablesFrom(Paint paint) was using the same Shader
for the copy as the initial Paint. Make sure that we are using a copy.
- implement a copy() API for shaders

See bug #7034321 Need Drawable RTL support

Change-Id: I4b9cee386edc72ad670723266333b85f4d2b0ab8
parent 5259ffba
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@ public class BitmapShader extends Shader {
    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
    public final Bitmap mBitmap;

    private TileMode mTileX;
    private TileMode mTileY;

    /**
     * Call this to create a new shader that will draw with a bitmap.
     *
@@ -37,11 +40,23 @@ public class BitmapShader extends Shader {
     */
    public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {
        mBitmap = bitmap;
        mTileX = tileX;
        mTileY = tileY;
        final int b = bitmap.ni();
        native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt);
        native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt);
    }

    /**
     * @hide
     */
    @Override
    protected Shader copy() {
        final BitmapShader copy = new BitmapShader(mBitmap, mTileX, mTileY);
        copyLocalMatrix(copy);
        return copy;
    }

    private static native int nativeCreate(int native_bitmap, int shaderTileModeX,
            int shaderTileModeY);
    private static native int nativePostCreate(int native_shader, int native_bitmap,
+38 −1
Original line number Diff line number Diff line
@@ -16,10 +16,22 @@

package android.graphics;

/** A subclass of shader that returns the coposition of two other shaders, combined by
/** A subclass of shader that returns the composition of two other shaders, combined by
    an {@link android.graphics.Xfermode} subclass.
*/
public class ComposeShader extends Shader {

    private static final int TYPE_XFERMODE = 1;
    private static final int TYPE_PORTERDUFFMODE = 2;

    /**
     * Type of the ComposeShader: can be either TYPE_XFERMODE or TYPE_PORTERDUFFMODE
     */
    private int mType;

    private Xfermode mXferMode;
    private PorterDuff.Mode mPorterDuffMode;

    /**
     * Hold onto the shaders to avoid GC.
     */
@@ -37,8 +49,10 @@ public class ComposeShader extends Shader {
                        is null, then SRC_OVER is assumed.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) {
        mType = TYPE_XFERMODE;
        mShaderA = shaderA;
        mShaderB = shaderB;
        mXferMode = mode;
        native_instance = nativeCreate1(shaderA.native_instance, shaderB.native_instance,
                (mode != null) ? mode.native_instance : 0);
        if (mode instanceof PorterDuffXfermode) {
@@ -59,14 +73,37 @@ public class ComposeShader extends Shader {
        @param mode     The PorterDuff mode that combines the colors from the two shaders.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) {
        mType = TYPE_PORTERDUFFMODE;
        mShaderA = shaderA;
        mShaderB = shaderB;
        mPorterDuffMode = mode;
        native_instance = nativeCreate2(shaderA.native_instance, shaderB.native_instance,
                mode.nativeInt);
        native_shader = nativePostCreate2(native_instance, shaderA.native_shader,
                shaderB.native_shader, mode.nativeInt);
    }

    /**
     * @hide
     */
    @Override
    protected Shader copy() {
        final ComposeShader copy;
        switch (mType) {
            case TYPE_XFERMODE:
                copy = new ComposeShader(mShaderA.copy(), mShaderB.copy(), mXferMode);
                break;
            case TYPE_PORTERDUFFMODE:
                copy = new ComposeShader(mShaderA.copy(), mShaderB.copy(), mPorterDuffMode);
                break;
            default:
                throw new IllegalArgumentException(
                        "ComposeShader should be created with either Xfermode or PorterDuffMode");
        }
        copyLocalMatrix(copy);
        return copy;
    }

    private static native int nativeCreate1(int native_shaderA, int native_shaderB,
            int native_mode);
    private static native int nativeCreate2(int native_shaderA, int native_shaderB,
+60 −1
Original line number Diff line number Diff line
@@ -17,6 +17,27 @@
package android.graphics;

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;

    private float mX0;
    private float mY0;
    private float mX1;
    private float mY1;
    private int[] mColors;
    private float[] mPositions;
    private int mColor0;
    private int mColor1;

    private TileMode mTileMode;

	/**	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
@@ -36,6 +57,14 @@ public class LinearGradient extends Shader {
        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;
        mPositions = positions;
        mTileMode = tile;
        native_instance = nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt);
        native_shader = nativePostCreate1(native_instance, x0, y0, x1, y1, colors, positions,
                tile.nativeInt);
@@ -52,11 +81,41 @@ public class LinearGradient extends Shader {
	*/
	public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
            TileMode tile) {
        mType = TYPE_COLOR_START_AND_COLOR_END;
        mX0 = x0;
        mY0 = y0;
        mX1 = x1;
        mY1 = y1;
        mColor0 = color0;
        mColor1 = color1;
        mTileMode = tile;
        native_instance = nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt);
        native_shader = nativePostCreate2(native_instance, x0, y0, x1, y1, color0, color1,
                tile.nativeInt);
    }

    /**
     * @hide
     */
    @Override
    protected Shader copy() {
        final LinearGradient copy;
        switch (mType) {
            case TYPE_COLORS_AND_POSITIONS:
                copy = new LinearGradient(mX0, mY0, mX1, mY1, mColors.clone(), mPositions.clone(),
                        mTileMode);
                break;
            case TYPE_COLOR_START_AND_COLOR_END:
                copy = new LinearGradient(mX0, mY0, mX1, mY1, mColor0, mColor1, mTileMode);
                break;
            default:
                throw new IllegalArgumentException("LinearGradient should be created with either " +
                        "colors and positions or start color and end color");
        }
        copyLocalMatrix(copy);
        return copy;
    }

    private native int nativeCreate1(float x0, float y0, float x1, float y1,
            int colors[], float positions[], int tileMode);
	private native int nativeCreate2(float x0, float y0, float x1, float y1,
+3 −1
Original line number Diff line number Diff line
@@ -421,7 +421,9 @@ public class Paint {
        mMaskFilter = paint.mMaskFilter;
        mPathEffect = paint.mPathEffect;
        mRasterizer = paint.mRasterizer;
        mShader = paint.mShader;
        if (paint.mShader != null) {
            mShader = paint.mShader.copy();
        }
        mTypeface = paint.mTypeface;
        mXfermode = paint.mXfermode;

+56 −1
Original line number Diff line number Diff line
@@ -18,6 +18,25 @@ package android.graphics;

public class RadialGradient extends Shader {

    private static final int TYPE_COLORS_AND_POSITIONS = 1;
    private static final int TYPE_COLOR_CENTER_AND_COLOR_EDGE = 2;

    /**
     * Type of the RadialGradient: can be either TYPE_COLORS_AND_POSITIONS or
     * TYPE_COLOR_CENTER_AND_COLOR_EDGE.
     */
    private int mType;

    private float mX;
    private float mY;
    private float mRadius;
    private int[] mColors;
    private float[] mPositions;
    private int mColor0;
    private int mColor1;

    private TileMode mTileMode;

	/**	Create a shader that draws a radial gradient given the center and radius.
        @param x        The x-coordinate of the center of the radius
        @param y        The y-coordinate of the center of the radius
@@ -39,6 +58,13 @@ public class RadialGradient extends Shader {
        if (positions != null && colors.length != positions.length) {
            throw new IllegalArgumentException("color and position arrays must be of equal length");
        }
        mType = TYPE_COLORS_AND_POSITIONS;
        mX = x;
        mY = y;
        mRadius = radius;
        mColors = colors;
        mPositions = positions;
        mTileMode = tile;
        native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt);
        native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions,
                tile.nativeInt);
@@ -57,11 +83,40 @@ public class RadialGradient extends Shader {
        if (radius <= 0) {
            throw new IllegalArgumentException("radius must be > 0");
        }
        mType = TYPE_COLOR_CENTER_AND_COLOR_EDGE;
        mX = x;
        mY = y;
        mRadius = radius;
        mColor0 = color0;
        mColor1 = color1;
        mTileMode = tile;
        native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
        native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
                tile.nativeInt);
    }

    /**
     * @hide
     */
    @Override
    protected Shader copy() {
        final RadialGradient copy;
        switch (mType) {
            case TYPE_COLORS_AND_POSITIONS:
                copy = new RadialGradient(mX, mY, mRadius, mColors.clone(), mPositions.clone(),
                        mTileMode);
                break;
            case TYPE_COLOR_CENTER_AND_COLOR_EDGE:
                copy = new RadialGradient(mX, mY, mRadius, mColor0, mColor1, mTileMode);
                break;
            default:
                throw new IllegalArgumentException("RadialGradient should be created with either " +
                        "colors and positions or center color and edge color");
        }
        copyLocalMatrix(copy);
        return copy;
    }

    private static native int nativeCreate1(float x, float y, float radius,
            int colors[], float positions[], int tileMode);
	private static native int nativeCreate2(float x, float y, float radius,
Loading