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

Commit e91aa0fa authored by Romain Guy's avatar Romain Guy
Browse files

Compute GradientDrawable's opacity correctly

The current implementation of GradientDrawable always assumes the shape needs
to be blended. This causes all windows to be considered translucent by default.
This change recomputes the opacity as needed to ensure windows are marked
opaque when they should.

Change-Id: Iaf291d889a6c5122ab00c9f5781df3e7f61547fa
parent a4b0e559
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.util.DisplayMetrics;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
import android.view.View;

import java.io.IOException;
import java.io.InputStream;
+0 −8
Original line number Diff line number Diff line
@@ -444,7 +444,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        int         mConstantMinimumWidth;
        int         mConstantMinimumHeight;

        boolean     mHaveOpacity = false;
        int         mOpacity;

        boolean     mHaveStateful = false;
@@ -493,7 +492,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
                mConstantWidth = orig.mConstantWidth;
                mConstantHeight = orig.mConstantHeight;
                
                mHaveOpacity = orig.mHaveOpacity;
                mOpacity = orig.mOpacity;
                mHaveStateful = orig.mHaveStateful;
                mStateful = orig.mStateful;
@@ -528,7 +526,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
            mDrawables[pos] = dr;
            mNumChildren++;
            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
            mHaveOpacity = false;
            mHaveStateful = false;

            mConstantPadding = null;
@@ -656,10 +653,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
        }

        public final int getOpacity() {
            if (mHaveOpacity) {
                return mOpacity;
            }

            final int N = getChildCount();
            final Drawable[] drawables = mDrawables;
            int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
@@ -667,7 +660,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
                op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
            }
            mOpacity = op;
            mHaveOpacity = true;
            return op;
        }

+51 −8
Original line number Diff line number Diff line
@@ -435,7 +435,8 @@ public class GradientDrawable extends Drawable {
        final int currFillAlpha = modulateAlpha(prevFillAlpha);
        final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);

        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint.getStrokeWidth() > 0;
        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
                mStrokePaint.getStrokeWidth() > 0;
        final boolean haveFill = currFillAlpha > 0;
        final GradientState st = mGradientState;
        /*  we need a layer iff we're drawing both a fill and stroke, and the
@@ -603,9 +604,9 @@ public class GradientDrawable extends Drawable {

    /**
     * <p>Changes this drawbale to use a single color instead of a gradient.</p>
     * <p><strong>Note</strong>: changing orientation will affect all instances
     * <p><strong>Note</strong>: changing color will affect all instances
     * of a drawable loaded from a resource. It is recommended to invoke
     * {@link #mutate()} before changing the orientation.</p>
     * {@link #mutate()} before changing the color.</p>
     *
     * @param argb The color used to fill the shape
     *
@@ -649,7 +650,7 @@ public class GradientDrawable extends Drawable {

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
        return mGradientState.mOpaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
    }

    @Override
@@ -1011,7 +1012,10 @@ public class GradientDrawable extends Drawable {
            } else {
                Log.w("drawable", "Bad element under <shape>: " + name);
            }

        }

        mGradientState.computeOpacity();
    }

    private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
@@ -1079,10 +1083,11 @@ public class GradientDrawable extends Drawable {
        private float mGradientRadius = 0.5f;
        private boolean mUseLevel;
        private boolean mUseLevelForShape;
        private boolean mOpaque;

        GradientState(Orientation orientation, int[] colors) {
            mOrientation = orientation;
            mColors = colors;
            setColors(colors);
        }

        public GradientState(GradientState state) {
@@ -1120,6 +1125,7 @@ public class GradientDrawable extends Drawable {
            mGradientRadius = state.mGradientRadius;
            mUseLevel = state.mUseLevel;
            mUseLevelForShape = state.mUseLevelForShape;
            mOpaque = state.mOpaque;
        }

        @Override
@@ -1139,6 +1145,7 @@ public class GradientDrawable extends Drawable {

        public void setShape(int shape) {
            mShape = shape;
            computeOpacity();
        }

        public void setGradientType(int gradient) {
@@ -1153,17 +1160,52 @@ public class GradientDrawable extends Drawable {
        public void setColors(int[] colors) {
            mHasSolidColor = false;
            mColors = colors;
            computeOpacity();
        }
        
        public void setSolidColor(int argb) {
            mHasSolidColor = true;
            mSolidColor = argb;
            mColors = null;
            computeOpacity();
        }

        private void computeOpacity() {
            if (mShape != RECTANGLE) {
                mOpaque = false;
                return;
            }

            if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
                mOpaque = false;
                return;
            }
            
            if (mHasSolidColor) {
                mOpaque = isOpaque(mSolidColor);
                return;
            }

            if (mColors != null) {
                for (int i = 0; i < mColors.length; i++) {
                    if (!isOpaque(mColors[i])) {
                        mOpaque = false;
                        return;
                    }
                }
            }

            mOpaque = true;
        }

        private static boolean isOpaque(int color) {
            return ((color >> 24) & 0xff) == 0xff;
        }

        public void setStroke(int width, int color) {
            mStrokeWidth = width;
            mStrokeColor = color;
            computeOpacity();
        }

        public void setStroke(int width, int color, float dashWidth, float dashGap) {
@@ -1171,6 +1213,7 @@ public class GradientDrawable extends Drawable {
            mStrokeColor = color;
            mStrokeDashWidth = dashWidth;
            mStrokeDashGap = dashGap;
            computeOpacity();
        }

        public void setCornerRadius(float radius) {