Skip to content

Commit e91aa0f

Browse files
author
Romain Guy
committed
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
1 parent a4b0e55 commit e91aa0f

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

graphics/java/android/graphics/drawable/Drawable.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import android.util.StateSet;
3838
import android.util.TypedValue;
3939
import android.util.Xml;
40-
import android.view.View;
4140

4241
import java.io.IOException;
4342
import java.io.InputStream;

graphics/java/android/graphics/drawable/DrawableContainer.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,6 @@ public abstract static class DrawableContainerState extends ConstantState {
444444
int mConstantMinimumWidth;
445445
int mConstantMinimumHeight;
446446

447-
boolean mHaveOpacity = false;
448447
int mOpacity;
449448

450449
boolean mHaveStateful = false;
@@ -493,7 +492,6 @@ public abstract static class DrawableContainerState extends ConstantState {
493492
mConstantWidth = orig.mConstantWidth;
494493
mConstantHeight = orig.mConstantHeight;
495494

496-
mHaveOpacity = orig.mHaveOpacity;
497495
mOpacity = orig.mOpacity;
498496
mHaveStateful = orig.mHaveStateful;
499497
mStateful = orig.mStateful;
@@ -528,7 +526,6 @@ public final int addChild(Drawable dr) {
528526
mDrawables[pos] = dr;
529527
mNumChildren++;
530528
mChildrenChangingConfigurations |= dr.getChangingConfigurations();
531-
mHaveOpacity = false;
532529
mHaveStateful = false;
533530

534531
mConstantPadding = null;
@@ -656,18 +653,13 @@ public final int getExitFadeDuration() {
656653
}
657654

658655
public final int getOpacity() {
659-
if (mHaveOpacity) {
660-
return mOpacity;
661-
}
662-
663656
final int N = getChildCount();
664657
final Drawable[] drawables = mDrawables;
665658
int op = N > 0 ? drawables[0].getOpacity() : PixelFormat.TRANSPARENT;
666659
for (int i = 1; i < N; i++) {
667660
op = Drawable.resolveOpacity(op, drawables[i].getOpacity());
668661
}
669662
mOpacity = op;
670-
mHaveOpacity = true;
671663
return op;
672664
}
673665

graphics/java/android/graphics/drawable/GradientDrawable.java

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ public void draw(Canvas canvas) {
435435
final int currFillAlpha = modulateAlpha(prevFillAlpha);
436436
final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
437437

438-
final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint.getStrokeWidth() > 0;
438+
final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
439+
mStrokePaint.getStrokeWidth() > 0;
439440
final boolean haveFill = currFillAlpha > 0;
440441
final GradientState st = mGradientState;
441442
/* we need a layer iff we're drawing both a fill and stroke, and the
@@ -603,9 +604,9 @@ private Path buildRing(GradientState st) {
603604

604605
/**
605606
* <p>Changes this drawbale to use a single color instead of a gradient.</p>
606-
* <p><strong>Note</strong>: changing orientation will affect all instances
607+
* <p><strong>Note</strong>: changing color will affect all instances
607608
* of a drawable loaded from a resource. It is recommended to invoke
608-
* {@link #mutate()} before changing the orientation.</p>
609+
* {@link #mutate()} before changing the color.</p>
609610
*
610611
* @param argb The color used to fill the shape
611612
*
@@ -649,7 +650,7 @@ public void setColorFilter(ColorFilter cf) {
649650

650651
@Override
651652
public int getOpacity() {
652-
return PixelFormat.TRANSLUCENT;
653+
return mGradientState.mOpaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
653654
}
654655

655656
@Override
@@ -1011,7 +1012,10 @@ public void inflate(Resources r, XmlPullParser parser,
10111012
} else {
10121013
Log.w("drawable", "Bad element under <shape>: " + name);
10131014
}
1015+
10141016
}
1017+
1018+
mGradientState.computeOpacity();
10151019
}
10161020

10171021
private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
@@ -1079,10 +1083,11 @@ final static class GradientState extends ConstantState {
10791083
private float mGradientRadius = 0.5f;
10801084
private boolean mUseLevel;
10811085
private boolean mUseLevelForShape;
1086+
private boolean mOpaque;
10821087

10831088
GradientState(Orientation orientation, int[] colors) {
10841089
mOrientation = orientation;
1085-
mColors = colors;
1090+
setColors(colors);
10861091
}
10871092

10881093
public GradientState(GradientState state) {
@@ -1120,6 +1125,7 @@ public GradientState(GradientState state) {
11201125
mGradientRadius = state.mGradientRadius;
11211126
mUseLevel = state.mUseLevel;
11221127
mUseLevelForShape = state.mUseLevelForShape;
1128+
mOpaque = state.mOpaque;
11231129
}
11241130

11251131
@Override
@@ -1139,6 +1145,7 @@ public int getChangingConfigurations() {
11391145

11401146
public void setShape(int shape) {
11411147
mShape = shape;
1148+
computeOpacity();
11421149
}
11431150

11441151
public void setGradientType(int gradient) {
@@ -1153,24 +1160,60 @@ public void setGradientCenter(float x, float y) {
11531160
public void setColors(int[] colors) {
11541161
mHasSolidColor = false;
11551162
mColors = colors;
1163+
computeOpacity();
11561164
}
11571165

11581166
public void setSolidColor(int argb) {
11591167
mHasSolidColor = true;
11601168
mSolidColor = argb;
11611169
mColors = null;
1170+
computeOpacity();
1171+
}
1172+
1173+
private void computeOpacity() {
1174+
if (mShape != RECTANGLE) {
1175+
mOpaque = false;
1176+
return;
1177+
}
1178+
1179+
if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
1180+
mOpaque = false;
1181+
return;
1182+
}
1183+
1184+
if (mHasSolidColor) {
1185+
mOpaque = isOpaque(mSolidColor);
1186+
return;
1187+
}
1188+
1189+
if (mColors != null) {
1190+
for (int i = 0; i < mColors.length; i++) {
1191+
if (!isOpaque(mColors[i])) {
1192+
mOpaque = false;
1193+
return;
1194+
}
1195+
}
1196+
}
1197+
1198+
mOpaque = true;
1199+
}
1200+
1201+
private static boolean isOpaque(int color) {
1202+
return ((color >> 24) & 0xff) == 0xff;
11621203
}
11631204

11641205
public void setStroke(int width, int color) {
11651206
mStrokeWidth = width;
11661207
mStrokeColor = color;
1208+
computeOpacity();
11671209
}
1168-
1210+
11691211
public void setStroke(int width, int color, float dashWidth, float dashGap) {
11701212
mStrokeWidth = width;
11711213
mStrokeColor = color;
11721214
mStrokeDashWidth = dashWidth;
11731215
mStrokeDashGap = dashGap;
1216+
computeOpacity();
11741217
}
11751218

11761219
public void setCornerRadius(float radius) {
@@ -1180,14 +1223,14 @@ public void setCornerRadius(float radius) {
11801223
mRadius = radius;
11811224
mRadiusArray = null;
11821225
}
1183-
1226+
11841227
public void setCornerRadii(float[] radii) {
11851228
mRadiusArray = radii;
11861229
if (radii == null) {
11871230
mRadius = 0;
11881231
}
11891232
}
1190-
1233+
11911234
public void setSize(int width, int height) {
11921235
mWidth = width;
11931236
mHeight = height;

0 commit comments

Comments
 (0)