summaryrefslogtreecommitdiff
path: root/graphics/java/android
diff options
context:
space:
mode:
author Chris Craik <ccraik@google.com> 2014-08-18 18:15:36 -0700
committer Chris Craik <ccraik@google.com> 2014-08-19 11:11:11 -0700
commitc49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76 (patch)
tree85dfe2eb4f6cea5983e2910ed0be05fba6284232 /graphics/java/android
parent49e057d7eedb44f5397781254acab4e0ef08a9cf (diff)
Don't cast shadows from gradients with transparent parts
bug:17070982 Change-Id: I607dd3c9397845fce53b7f097ec0b57246077ea1
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/graphics/Outline.java38
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java32
2 files changed, 38 insertions, 32 deletions
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3177023edda7..4bf0b71b6fc2 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -18,15 +18,15 @@ package android.graphics;
import android.annotation.NonNull;
import android.graphics.drawable.Drawable;
-import android.view.View;
/**
* Defines a simple shape, used for bounding graphical regions.
* <p>
- * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
- * View, or to clip the contents of the View.
+ * Can be computed for a View, or computed by a Drawable, to drive the shape of
+ * shadows cast by a View, or to clip the contents of the View.
*
- * @see View#setOutline(Outline)
+ * @see android.view.ViewOutlineProvider
+ * @see android.view.View#setOutlineProvider(android.view.ViewOutlineProvider)
* @see Drawable#getOutline(Outline)
*/
public final class Outline {
@@ -79,21 +79,27 @@ public final class Outline {
/**
* Returns whether the outline can be used to clip a View.
+ * <p>
+ * Currently, only Outlines that can be represented as a rectangle, circle,
+ * or round rect support clipping.
*
- * Currently, only outlines that can be represented as a rectangle, circle, or round rect
- * support clipping.
- *
- * @see {@link View#setClipToOutline(boolean)}
+ * @see {@link android.view.View#setClipToOutline(boolean)}
*/
public boolean canClip() {
return !isEmpty() && mRect != null;
}
/**
- * Sets the alpha represented by the Outline.
- *
- * Content producing a fully opaque (alpha = 1.0f) outline is assumed by the drawing system
- * to fully cover content beneath it, meaning content beneath may be optimized away.
+ * Sets the alpha represented by the Outline - the degree to which the
+ * producer is guaranteed to be opaque over the Outline's shape.
+ * <p>
+ * An alpha value of <code>0.0f</code> either represents completely
+ * transparent content, or content that isn't guaranteed to fill the shape
+ * it publishes.
+ * <p>
+ * Content producing a fully opaque (alpha = <code>1.0f</code>) outline is
+ * assumed by the drawing system to fully cover content beneath it,
+ * meaning content beneath may be optimized away.
*/
public void setAlpha(float alpha) {
mAlpha = alpha;
@@ -130,7 +136,8 @@ public final class Outline {
}
/**
- * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
+ * Sets the Outline to the rounded rect defined by the input rect, and
+ * corner radius.
*/
public void setRect(int left, int top, int right, int bottom) {
setRoundRect(left, top, right, bottom, 0.0f);
@@ -145,7 +152,7 @@ public final class Outline {
/**
* Sets the Outline to the rounded rect defined by the input rect, and corner radius.
- *
+ * <p>
* Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
*/
public void setRoundRect(int left, int top, int right, int bottom, float radius) {
@@ -196,7 +203,8 @@ public final class Outline {
}
/**
- * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
+ * Sets the Constructs an Outline from a
+ * {@link android.graphics.Path#isConvex() convex path}.
*/
public void setConvexPath(@NonNull Path convexPath) {
if (convexPath.isEmpty()) {
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index a383aabd5a80..29b914153461 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -820,7 +820,7 @@ public class GradientDrawable extends Drawable {
@Override
public int getOpacity() {
- return (mAlpha == 255 && mGradientState.mOpaque) ?
+ return (mAlpha == 255 && mGradientState.mOpaqueOverBounds) ?
PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
}
@@ -1413,7 +1413,8 @@ public class GradientDrawable extends Drawable {
public void getOutline(Outline outline) {
final GradientState st = mGradientState;
final Rect bounds = getBounds();
- outline.setAlpha(mAlpha / 255.0f);
+ // only report non-zero alpha if shape being drawn is opaque
+ outline.setAlpha(st.mOpaqueOverShape ? (mAlpha / 255.0f) : 0.0f);
switch (st.mShape) {
case RECTANGLE:
@@ -1492,7 +1493,8 @@ public class GradientDrawable extends Drawable {
private int mGradientRadiusType = RADIUS_TYPE_PIXELS;
private boolean mUseLevel;
private boolean mUseLevelForShape;
- private boolean mOpaque;
+ private boolean mOpaqueOverBounds;
+ private boolean mOpaqueOverShape;
int[] mThemeAttrs;
int[] mAttrSize;
@@ -1544,7 +1546,7 @@ public class GradientDrawable extends Drawable {
mGradientRadiusType = state.mGradientRadiusType;
mUseLevel = state.mUseLevel;
mUseLevelForShape = state.mUseLevelForShape;
- mOpaque = state.mOpaque;
+ mOpaqueOverBounds = state.mOpaqueOverBounds;
mThemeAttrs = state.mThemeAttrs;
mAttrSize = state.mAttrSize;
mAttrGradient = state.mAttrGradient;
@@ -1606,40 +1608,36 @@ public class GradientDrawable extends Drawable {
}
private void computeOpacity() {
- if (mShape != RECTANGLE) {
- mOpaque = false;
- return;
- }
-
- if (mRadius > 0 || mRadiusArray != null) {
- mOpaque = false;
- return;
- }
+ mOpaqueOverBounds = false;
+ mOpaqueOverShape = false;
+ // First test opacity of all colors
if (mStrokeWidth > 0) {
if (mStrokeColorStateList != null) {
if (!mStrokeColorStateList.isOpaque()) {
- mOpaque = false;
return;
}
}
}
if (mColorStateList != null && !mColorStateList.isOpaque()) {
- mOpaque = false;
return;
}
if (mColors != null) {
for (int i = 0; i < mColors.length; i++) {
if (!isOpaque(mColors[i])) {
- mOpaque = false;
return;
}
}
}
- mOpaque = true;
+ // Colors are opaque, so opaqueOverShape=true,
+ mOpaqueOverShape = true;
+ // and opaqueOverBounds=true if shape fills bounds
+ mOpaqueOverBounds = mShape == RECTANGLE
+ && mRadius <= 0
+ && mRadiusArray == null;
}
private static boolean isOpaque(int color) {