OSDN Git Service

Prevent RevealDrawable from drawing mask when layer is empty
authorAlan Viverette <alanv@google.com>
Fri, 17 Jan 2014 23:38:20 +0000 (15:38 -0800)
committerAlan Viverette <alanv@google.com>
Fri, 17 Jan 2014 23:38:20 +0000 (15:38 -0800)
Compositing the mask layer into an empty layer using SRC_IN will
actually composite into the layer UNDER the empty layer.

Change-Id: I5ba434b0d7e6a5bc707fe842a5db82ae33066912

graphics/java/android/graphics/drawable/RevealDrawable.java
graphics/java/android/graphics/drawable/Ripple.java

index c357ae1..38765e8 100644 (file)
@@ -18,6 +18,7 @@ package android.graphics.drawable;
 
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
@@ -248,6 +249,7 @@ public class RevealDrawable extends LayerDrawable {
         }
 
         // Draw ripple mask into a buffer that merges using SRC_OVER.
+        boolean needsMask = false;
         int layerSaveCount = -1;
         int n = activeRipples.size();
         for (int i = 0; i < n; i++) {
@@ -261,7 +263,7 @@ public class RevealDrawable extends LayerDrawable {
                     layerSaveCount = canvas.saveLayer(0, 0, width, height, null, 0);
                 }
 
-                ripple.draw(canvas, mRipplePaint);
+                needsMask |= ripple.draw(canvas, mRipplePaint);
             }
         }
 
@@ -269,15 +271,18 @@ public class RevealDrawable extends LayerDrawable {
         // into another layer and composite using SRC_IN, then composite onto
         // the original canvas.
         if (layerSaveCount >= 0) {
-            if (mMaskingPaint == null) {
-                mMaskingPaint = new Paint();
-                mMaskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+            if (needsMask) {
+                if (mMaskingPaint == null) {
+                    mMaskingPaint = new Paint();
+                    mMaskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+                }
+
+                // TODO: When Drawable.setXfermode() is supported by all drawables,
+                // we won't need an extra layer.
+                canvas.saveLayer(0, 0, width, height, mMaskingPaint, 0);
+                getDrawable(1).draw(canvas);
             }
 
-            // TODO: When Drawable.setXfermode() is supported by all drawables,
-            // we won't need an extra layer.
-            canvas.saveLayer(0, 0, width, height, mMaskingPaint, 0);
-            getDrawable(1).draw(canvas);
             canvas.restoreToCount(layerSaveCount);
         }
     }
index 6378cb7..543d2a6 100644 (file)
@@ -160,7 +160,7 @@ class Ripple {
         }
     }
 
-    public void draw(Canvas c, Paint p) {
+    public boolean draw(Canvas c, Paint p) {
         final Rect bounds = mBounds;
         final Rect padding = mPadding;
         final float dX = Math.max(mX, bounds.right - mX);
@@ -221,26 +221,34 @@ class Ripple {
             }
         }
 
-        if (exitState <= 0) {
-            // Exit state isn't showing, so we can simplify to a solid
-            // circle.
-            if (outerRadius > 0) {
-                p.setAlpha(maxAlpha);
-                p.setStyle(Style.FILL);
-                c.drawCircle(x, y, outerRadius, p);
-            }
-        } else {
-            // Both states are showing, so we need a circular stroke.
-            final float innerRadius = MathUtils.lerp(0, outerRadius, exitState);
-            final float strokeWidth = outerRadius - innerRadius;
-            if (strokeWidth > 0) {
-                final float strokeRadius = innerRadius + strokeWidth / 2f;
-                final int alpha = (int) (MathUtils.lerp(maxAlpha, 0, exitState) + 0.5f);
-                p.setAlpha(alpha);
-                p.setStyle(Style.STROKE);
-                p.setStrokeWidth(strokeWidth);
-                c.drawCircle(x, y, strokeRadius, p);
+        if (maxAlpha > 0) {
+            if (exitState <= 0) {
+                // Exit state isn't showing, so we can simplify to a solid
+                // circle.
+                if (outerRadius > 0) {
+                    p.setAlpha(maxAlpha);
+                    p.setStyle(Style.FILL);
+                    c.drawCircle(x, y, outerRadius, p);
+                    return true;
+                }
+            } else {
+                // Both states are showing, so we need a circular stroke.
+                final float innerRadius = MathUtils.lerp(0, outerRadius, exitState);
+                final float strokeWidth = outerRadius - innerRadius;
+                if (strokeWidth > 0) {
+                    final float strokeRadius = innerRadius + strokeWidth / 2f;
+                    final int alpha = (int) (MathUtils.lerp(maxAlpha, 0, exitState) + 0.5f);
+                    if (alpha > 0) {
+                        p.setAlpha(alpha);
+                        p.setStyle(Style.STROKE);
+                        p.setStrokeWidth(strokeWidth);
+                        c.drawCircle(x, y, strokeRadius, p);
+                        return true;
+                    }
+                }
             }
         }
+
+        return false;
     }
 }