From e91aa0fa64db892194ba82ec7d41df6fb9185471 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 18 Sep 2012 15:37:24 -0700 Subject: 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 --- .../java/android/graphics/drawable/Drawable.java | 1 - .../graphics/drawable/DrawableContainer.java | 8 --- .../graphics/drawable/GradientDrawable.java | 59 +++++++++++++++++++--- 3 files changed, 51 insertions(+), 17 deletions(-) (limited to 'graphics') diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 020a54f..41f6db9 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -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; diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 486390c..41b272d 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -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; } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 21344f4..42be657 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -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 { /** *

Changes this drawbale to use a single color instead of a gradient.

- *

Note: changing orientation will affect all instances + *

Note: changing color will affect all instances * of a drawable loaded from a resource. It is recommended to invoke - * {@link #mutate()} before changing the orientation.

+ * {@link #mutate()} before changing the color.

* * @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 : " + 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,24 +1160,60 @@ 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) { mStrokeWidth = width; mStrokeColor = color; mStrokeDashWidth = dashWidth; mStrokeDashGap = dashGap; + computeOpacity(); } public void setCornerRadius(float radius) { @@ -1180,14 +1223,14 @@ public class GradientDrawable extends Drawable { mRadius = radius; mRadiusArray = null; } - + public void setCornerRadii(float[] radii) { mRadiusArray = radii; if (radii == null) { mRadius = 0; } } - + public void setSize(int width, int height) { mWidth = width; mHeight = height; -- cgit v1.1