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

Commit 6dfa60f3 authored by Alan Viverette's avatar Alan Viverette
Browse files

Avoid extra saveLayer calls in RippleDrawable, fix docs

Also fixes opacity returned from InsetDrawable to accurately reflect
the transparent inset area and updates button to correctly use tint.

BUG: 18226391
Change-Id: Ia9a88d9d663990a6829d2f251c7f59ea2a79d816
parent 3a0d878a
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -21,9 +21,10 @@
       android:insetTop="@dimen/button_inset_vertical_material"
       android:insetTop="@dimen/button_inset_vertical_material"
       android:insetRight="@dimen/button_inset_horizontal_material"
       android:insetRight="@dimen/button_inset_horizontal_material"
       android:insetBottom="@dimen/button_inset_vertical_material">
       android:insetBottom="@dimen/button_inset_vertical_material">
    <shape android:shape="rectangle">
    <shape android:shape="rectangle"
           android:tint="?attr/colorButtonNormal">
        <corners android:radius="@dimen/control_corner_material" />
        <corners android:radius="@dimen/control_corner_material" />
        <solid android:color="?attr/colorButtonNormal" />
        <solid android:color="@color/white" />
        <padding android:left="@dimen/button_padding_horizontal_material"
        <padding android:left="@dimen/button_padding_horizontal_material"
                 android:top="@dimen/button_padding_vertical_material"
                 android:top="@dimen/button_padding_vertical_material"
                 android:right="@dimen/button_padding_horizontal_material"
                 android:right="@dimen/button_padding_horizontal_material"
+8 −1
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.AttributeSet;
@@ -317,7 +318,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {


    @Override
    @Override
    public int getOpacity() {
    public int getOpacity() {
        return mState.mDrawable.getOpacity();
        final InsetState state = mState;
        final int opacity = state.mDrawable.getOpacity();
        if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0
                || state.mInsetRight > 0 || state.mInsetBottom > 0)) {
            return PixelFormat.TRANSLUCENT;
        }
        return opacity;
    }
    }


    @Override
    @Override
+43 −55
Original line number Original line Diff line number Diff line
@@ -22,11 +22,8 @@ import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.CanvasProperty;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.Xfermode;
import android.util.MathUtils;
import android.util.MathUtils;
import android.view.HardwareCanvas;
import android.view.HardwareCanvas;
import android.view.RenderNodeAnimator;
import android.view.RenderNodeAnimator;
@@ -51,19 +48,12 @@ class Ripple {
    // Hardware animators.
    // Hardware animators.
    private final ArrayList<RenderNodeAnimator> mRunningAnimations =
    private final ArrayList<RenderNodeAnimator> mRunningAnimations =
            new ArrayList<RenderNodeAnimator>();
            new ArrayList<RenderNodeAnimator>();
    private final ArrayList<RenderNodeAnimator> mPendingAnimations =
            new ArrayList<RenderNodeAnimator>();


    private final RippleDrawable mOwner;
    private final RippleDrawable mOwner;


    /** Bounds used for computing max radius. */
    /** Bounds used for computing max radius. */
    private final Rect mBounds;
    private final Rect mBounds;


    /** ARGB color for drawing this ripple. */
    private int mColor;

    private Xfermode mXfermode;

    /** Maximum ripple radius. */
    /** Maximum ripple radius. */
    private float mOuterRadius;
    private float mOuterRadius;


@@ -112,6 +102,10 @@ class Ripple {
    /** Whether we were canceled externally and should avoid self-removal. */
    /** Whether we were canceled externally and should avoid self-removal. */
    private boolean mCanceled;
    private boolean mCanceled;


    private boolean mHasPendingHardwareExit;
    private int mPendingRadiusDuration;
    private int mPendingOpacityDuration;

    /**
    /**
     * Creates a new ripple.
     * Creates a new ripple.
     */
     */
@@ -217,10 +211,6 @@ class Ripple {
     * Draws the ripple centered at (0,0) using the specified paint.
     * Draws the ripple centered at (0,0) using the specified paint.
     */
     */
    public boolean draw(Canvas c, Paint p) {
    public boolean draw(Canvas c, Paint p) {
        // Store the color and xfermode, we might need them later.
        mColor = p.getColor();
        mXfermode = p.getXfermode();

        final boolean canUseHardware = c.isHardwareAccelerated();
        final boolean canUseHardware = c.isHardwareAccelerated();
        if (mCanUseHardware != canUseHardware && mCanUseHardware) {
        if (mCanUseHardware != canUseHardware && mCanUseHardware) {
            // We've switched from hardware to non-hardware mode. Panic.
            // We've switched from hardware to non-hardware mode. Panic.
@@ -229,8 +219,8 @@ class Ripple {
        mCanUseHardware = canUseHardware;
        mCanUseHardware = canUseHardware;


        final boolean hasContent;
        final boolean hasContent;
        if (canUseHardware && mHardwareAnimating) {
        if (canUseHardware && (mHardwareAnimating || mHasPendingHardwareExit)) {
            hasContent = drawHardware((HardwareCanvas) c);
            hasContent = drawHardware((HardwareCanvas) c, p);
        } else {
        } else {
            hasContent = drawSoftware(c, p);
            hasContent = drawSoftware(c, p);
        }
        }
@@ -238,24 +228,10 @@ class Ripple {
        return hasContent;
        return hasContent;
    }
    }


    private boolean drawHardware(HardwareCanvas c) {
    private boolean drawHardware(HardwareCanvas c, Paint p) {
        // If we have any pending hardware animations, cancel any running
        if (mHasPendingHardwareExit) {
        // animations and start those now.
        final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
        final int N = pendingAnimations.size();
        if (N > 0) {
            cancelHardwareAnimations(false);
            cancelHardwareAnimations(false);

            startPendingHardwareExit(c, p);
            // We canceled old animations, but we're about to run new ones.
            mHardwareAnimating = true;

            for (int i = 0; i < N; i++) {
                pendingAnimations.get(i).setTarget(c);
                pendingAnimations.get(i).start();
            }

            mRunningAnimations.addAll(pendingAnimations);
            pendingAnimations.clear();
        }
        }


        c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
        c.drawCircle(mPropX, mPropY, mPropRadius, mPropPaint);
@@ -347,8 +323,6 @@ class Ripple {
     * Starts the exit animation.
     * Starts the exit animation.
     */
     */
    public void exit() {
    public void exit() {
        cancel();

        final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
        final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
        final float remaining;
        final float remaining;
        if (mAnimRadius != null && mAnimRadius.isRunning()) {
        if (mAnimRadius != null && mAnimRadius.isRunning()) {
@@ -357,19 +331,33 @@ class Ripple {
            remaining = mOuterRadius;
            remaining = mOuterRadius;
        }
        }


        cancel();

        final int radiusDuration = (int) (1000 * Math.sqrt(remaining / (WAVE_TOUCH_UP_ACCELERATION
        final int radiusDuration = (int) (1000 * Math.sqrt(remaining / (WAVE_TOUCH_UP_ACCELERATION
                + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5);
                + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5);
        final int opacityDuration = (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f);
        final int opacityDuration = (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f);


        if (mCanUseHardware) {
        if (mCanUseHardware) {
            exitHardware(radiusDuration, opacityDuration);
            createPendingHardwareExit(radiusDuration, opacityDuration);
        } else {
        } else {
            exitSoftware(radiusDuration, opacityDuration);
            exitSoftware(radiusDuration, opacityDuration);
        }
        }
    }
    }


    private void exitHardware(int radiusDuration, int opacityDuration) {
    private void createPendingHardwareExit(int radiusDuration, int opacityDuration) {
        mPendingAnimations.clear();
        mHasPendingHardwareExit = true;
        mPendingRadiusDuration = radiusDuration;
        mPendingOpacityDuration = opacityDuration;

        // The animation will start on the next draw().
        invalidateSelf();
    }

    private void startPendingHardwareExit(HardwareCanvas c, Paint p) {
        mHasPendingHardwareExit = false;

        final int radiusDuration = mPendingRadiusDuration;
        final int opacityDuration = mPendingOpacityDuration;


        final float startX = MathUtils.lerp(
        final float startX = MathUtils.lerp(
                mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
                mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
@@ -377,12 +365,8 @@ class Ripple {
                mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
                mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);


        final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
        final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
        final Paint paint = getTempPaint();
        final Paint paint = getTempPaint(p);
        paint.setAntiAlias(true);
        paint.setAlpha((int) (paint.getAlpha() * mOpacity + 0.5f));
        paint.setColor(mColor);
        paint.setXfermode(mXfermode);
        paint.setAlpha((int) (Color.alpha(mColor) * mOpacity + 0.5f));
        paint.setStyle(Style.FILL);
        mPropPaint = CanvasProperty.createPaint(paint);
        mPropPaint = CanvasProperty.createPaint(paint);
        mPropRadius = CanvasProperty.createFloat(startRadius);
        mPropRadius = CanvasProperty.createFloat(startRadius);
        mPropX = CanvasProperty.createFloat(startX);
        mPropX = CanvasProperty.createFloat(startX);
@@ -391,25 +375,33 @@ class Ripple {
        final RenderNodeAnimator radiusAnim = new RenderNodeAnimator(mPropRadius, mOuterRadius);
        final RenderNodeAnimator radiusAnim = new RenderNodeAnimator(mPropRadius, mOuterRadius);
        radiusAnim.setDuration(radiusDuration);
        radiusAnim.setDuration(radiusDuration);
        radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
        radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
        radiusAnim.setTarget(c);
        radiusAnim.start();


        final RenderNodeAnimator xAnim = new RenderNodeAnimator(mPropX, mOuterX);
        final RenderNodeAnimator xAnim = new RenderNodeAnimator(mPropX, mOuterX);
        xAnim.setDuration(radiusDuration);
        xAnim.setDuration(radiusDuration);
        xAnim.setInterpolator(DECEL_INTERPOLATOR);
        xAnim.setInterpolator(DECEL_INTERPOLATOR);
        xAnim.setTarget(c);
        xAnim.start();


        final RenderNodeAnimator yAnim = new RenderNodeAnimator(mPropY, mOuterY);
        final RenderNodeAnimator yAnim = new RenderNodeAnimator(mPropY, mOuterY);
        yAnim.setDuration(radiusDuration);
        yAnim.setDuration(radiusDuration);
        yAnim.setInterpolator(DECEL_INTERPOLATOR);
        yAnim.setInterpolator(DECEL_INTERPOLATOR);
        yAnim.setTarget(c);
        yAnim.start();


        final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPropPaint,
        final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPropPaint,
                RenderNodeAnimator.PAINT_ALPHA, 0);
                RenderNodeAnimator.PAINT_ALPHA, 0);
        opacityAnim.setDuration(opacityDuration);
        opacityAnim.setDuration(opacityDuration);
        opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
        opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
        opacityAnim.addListener(mAnimationListener);
        opacityAnim.addListener(mAnimationListener);
        opacityAnim.setTarget(c);
        opacityAnim.start();


        mPendingAnimations.add(radiusAnim);
        mRunningAnimations.add(radiusAnim);
        mPendingAnimations.add(opacityAnim);
        mRunningAnimations.add(opacityAnim);
        mPendingAnimations.add(xAnim);
        mRunningAnimations.add(xAnim);
        mPendingAnimations.add(yAnim);
        mRunningAnimations.add(yAnim);


        mHardwareAnimating = true;
        mHardwareAnimating = true;


@@ -418,8 +410,6 @@ class Ripple {
        mTweenX = 1;
        mTweenX = 1;
        mTweenY = 1;
        mTweenY = 1;
        mTweenRadius = 1;
        mTweenRadius = 1;

        invalidateSelf();
    }
    }


    /**
    /**
@@ -455,10 +445,11 @@ class Ripple {
        }
        }
    }
    }


    private Paint getTempPaint() {
    private Paint getTempPaint(Paint original) {
        if (mTempPaint == null) {
        if (mTempPaint == null) {
            mTempPaint = new Paint();
            mTempPaint = new Paint();
        }
        }
        mTempPaint.set(original);
        return mTempPaint;
        return mTempPaint;
    }
    }


@@ -539,10 +530,7 @@ class Ripple {
        }
        }
        runningAnimations.clear();
        runningAnimations.clear();


        if (cancelPending && !mPendingAnimations.isEmpty()) {
        mHasPendingHardwareExit = false;
            mPendingAnimations.clear();
        }

        mHardwareAnimating = false;
        mHardwareAnimating = false;
    }
    }


+40 −45
Original line number Original line Diff line number Diff line
@@ -24,9 +24,7 @@ import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.CanvasProperty;
import android.graphics.Color;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.Xfermode;
import android.util.MathUtils;
import android.util.MathUtils;
import android.view.HardwareCanvas;
import android.view.HardwareCanvas;
import android.view.RenderNodeAnimator;
import android.view.RenderNodeAnimator;
@@ -53,8 +51,6 @@ class RippleBackground {
    // Hardware animators.
    // Hardware animators.
    private final ArrayList<RenderNodeAnimator> mRunningAnimations =
    private final ArrayList<RenderNodeAnimator> mRunningAnimations =
            new ArrayList<RenderNodeAnimator>();
            new ArrayList<RenderNodeAnimator>();
    private final ArrayList<RenderNodeAnimator> mPendingAnimations =
            new ArrayList<RenderNodeAnimator>();


    private final RippleDrawable mOwner;
    private final RippleDrawable mOwner;


@@ -64,8 +60,6 @@ class RippleBackground {
    /** ARGB color for drawing this ripple. */
    /** ARGB color for drawing this ripple. */
    private int mColor;
    private int mColor;


    private Xfermode mXfermode;

    /** Maximum ripple radius. */
    /** Maximum ripple radius. */
    private float mOuterRadius;
    private float mOuterRadius;


@@ -98,6 +92,11 @@ class RippleBackground {
    /** Whether we have an explicit maximum radius. */
    /** Whether we have an explicit maximum radius. */
    private boolean mHasMaxRadius;
    private boolean mHasMaxRadius;


    private boolean mHasPendingHardwareExit;
    private int mPendingOpacityDuration;
    private int mPendingInflectionDuration;
    private int mPendingInflectionOpacity;

    /**
    /**
     * Creates a new ripple.
     * Creates a new ripple.
     */
     */
@@ -144,9 +143,7 @@ class RippleBackground {
     * Draws the ripple centered at (0,0) using the specified paint.
     * Draws the ripple centered at (0,0) using the specified paint.
     */
     */
    public boolean draw(Canvas c, Paint p) {
    public boolean draw(Canvas c, Paint p) {
        // Store the color and xfermode, we might need them later.
        mColor = p.getColor();
        mColor = p.getColor();
        mXfermode = p.getXfermode();


        final boolean canUseHardware = c.isHardwareAccelerated();
        final boolean canUseHardware = c.isHardwareAccelerated();
        if (mCanUseHardware != canUseHardware && mCanUseHardware) {
        if (mCanUseHardware != canUseHardware && mCanUseHardware) {
@@ -156,8 +153,8 @@ class RippleBackground {
        mCanUseHardware = canUseHardware;
        mCanUseHardware = canUseHardware;


        final boolean hasContent;
        final boolean hasContent;
        if (canUseHardware && mHardwareAnimating) {
        if (canUseHardware && (mHardwareAnimating || mHasPendingHardwareExit)) {
            hasContent = drawHardware((HardwareCanvas) c);
            hasContent = drawHardware((HardwareCanvas) c, p);
        } else {
        } else {
            hasContent = drawSoftware(c, p);
            hasContent = drawSoftware(c, p);
        }
        }
@@ -169,24 +166,10 @@ class RippleBackground {
        return (mCanUseHardware && mHardwareAnimating) || (mOuterOpacity > 0 && mOuterRadius > 0);
        return (mCanUseHardware && mHardwareAnimating) || (mOuterOpacity > 0 && mOuterRadius > 0);
    }
    }


    private boolean drawHardware(HardwareCanvas c) {
    private boolean drawHardware(HardwareCanvas c, Paint p) {
        // If we have any pending hardware animations, cancel any running
        if (mHasPendingHardwareExit) {
        // animations and start those now.
        final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
        final int N = pendingAnimations.size();
        if (N > 0) {
            cancelHardwareAnimations(false);
            cancelHardwareAnimations(false);

            startPendingHardwareExit(c, p);
            // We canceled old animations, but we're about to run new ones.
            mHardwareAnimating = true;

            for (int i = 0; i < N; i++) {
                pendingAnimations.get(i).setTarget(c);
                pendingAnimations.get(i).start();
            }

            mRunningAnimations.addAll(pendingAnimations);
            pendingAnimations.clear();
        }
        }


        c.drawCircle(mPropOuterX, mPropOuterY, mPropOuterRadius, mPropOuterPaint);
        c.drawCircle(mPropOuterX, mPropOuterY, mPropOuterRadius, mPropOuterPaint);
@@ -263,21 +246,32 @@ class RippleBackground {
                + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
                + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);


        if (mCanUseHardware) {
        if (mCanUseHardware) {
            exitHardware(opacityDuration, inflectionDuration, inflectionOpacity);
            createPendingHardwareExit(opacityDuration, inflectionDuration, inflectionOpacity);
        } else {
        } else {
            exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
            exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
        }
        }
    }
    }


    private void exitHardware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
    private void createPendingHardwareExit(
        mPendingAnimations.clear();
            int opacityDuration, int inflectionDuration, int inflectionOpacity) {
        mHasPendingHardwareExit = true;
        mPendingOpacityDuration = opacityDuration;
        mPendingInflectionDuration = inflectionDuration;
        mPendingInflectionOpacity = inflectionOpacity;


        final Paint outerPaint = getTempPaint();
        // The animation will start on the next draw().
        outerPaint.setAntiAlias(true);
        invalidateSelf();
        outerPaint.setXfermode(mXfermode);
    }
        outerPaint.setColor(mColor);

        outerPaint.setAlpha((int) (Color.alpha(mColor) * mOuterOpacity + 0.5f));
    private void startPendingHardwareExit(HardwareCanvas c, Paint p) {
        outerPaint.setStyle(Style.FILL);
        mHasPendingHardwareExit = false;

        final int opacityDuration = mPendingOpacityDuration;
        final int inflectionDuration = mPendingInflectionDuration;
        final int inflectionOpacity = mPendingInflectionOpacity;

        final Paint outerPaint = getTempPaint(p);
        outerPaint.setAlpha((int) (outerPaint.getAlpha() * mOuterOpacity + 0.5f));
        mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
        mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
        mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
        mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
        mPropOuterX = CanvasProperty.createFloat(mOuterX);
        mPropOuterX = CanvasProperty.createFloat(mOuterX);
@@ -301,8 +295,10 @@ class RippleBackground {
                outerFadeOutAnim.setStartDelay(inflectionDuration);
                outerFadeOutAnim.setStartDelay(inflectionDuration);
                outerFadeOutAnim.setStartValue(inflectionOpacity);
                outerFadeOutAnim.setStartValue(inflectionOpacity);
                outerFadeOutAnim.addListener(mAnimationListener);
                outerFadeOutAnim.addListener(mAnimationListener);
                outerFadeOutAnim.setTarget(c);
                outerFadeOutAnim.start();


                mPendingAnimations.add(outerFadeOutAnim);
                mRunningAnimations.add(outerFadeOutAnim);
            } else {
            } else {
                outerOpacityAnim.addListener(mAnimationListener);
                outerOpacityAnim.addListener(mAnimationListener);
            }
            }
@@ -314,14 +310,15 @@ class RippleBackground {
            outerOpacityAnim.addListener(mAnimationListener);
            outerOpacityAnim.addListener(mAnimationListener);
        }
        }


        mPendingAnimations.add(outerOpacityAnim);
        outerOpacityAnim.setTarget(c);
        outerOpacityAnim.start();

        mRunningAnimations.add(outerOpacityAnim);


        mHardwareAnimating = true;
        mHardwareAnimating = true;


        // Set up the software values to match the hardware end values.
        // Set up the software values to match the hardware end values.
        mOuterOpacity = 0;
        mOuterOpacity = 0;

        invalidateSelf();
    }
    }


    /**
    /**
@@ -340,10 +337,11 @@ class RippleBackground {
        }
        }
    }
    }


    private Paint getTempPaint() {
    private Paint getTempPaint(Paint original) {
        if (mTempPaint == null) {
        if (mTempPaint == null) {
            mTempPaint = new Paint();
            mTempPaint = new Paint();
        }
        }
        mTempPaint.set(original);
        return mTempPaint;
        return mTempPaint;
    }
    }


@@ -422,10 +420,7 @@ class RippleBackground {
        }
        }
        runningAnimations.clear();
        runningAnimations.clear();


        if (cancelPending && !mPendingAnimations.isEmpty()) {
        mHasPendingHardwareExit = false;
            mPendingAnimations.clear();
        }

        mHardwareAnimating = false;
        mHardwareAnimating = false;
    }
    }


+162 −95

File changed.

Preview size limit exceeded, changes collapsed.