Fix shadow painting in layoutlib
Shadows could be painted outside of the allowed drawing region for the components for which they are the shadow. Bug: http://b.android.com/215402 Change-Id: I2d2821b745147f3723e8f11d648094fcd684fe51 (cherry picked from commit 9702fffc768db43d0aba4fb1bea54af50af11361)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import com.android.layoutlib.bridge.impl.GcSnapshot;
|
||||
import com.android.layoutlib.bridge.impl.ResourceHelper;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
@@ -32,6 +33,8 @@ import android.graphics.RectF;
|
||||
import android.graphics.Region.Op;
|
||||
import android.graphics.Shader.TileMode;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* Paints shadow for rounded rectangles. Inspiration from CardView. Couldn't use that directly,
|
||||
* since it modifies the size of the content, that we can't do.
|
||||
@@ -127,9 +130,16 @@ public class RectShadowPainter {
|
||||
int saved = canvas.save();
|
||||
// Usually canvas has been translated to the top left corner of the view when this is
|
||||
// called. So, setting a clip rect at 0,0 will clip the top left part of the shadow.
|
||||
// Thus, we just expand in each direction by width and height of the canvas.
|
||||
canvas.clipRect(-canvas.getWidth(), -canvas.getHeight(), canvas.getWidth(),
|
||||
canvas.getHeight(), Op.REPLACE);
|
||||
// Thus, we just expand in each direction by width and height of the canvas, while staying
|
||||
// inside the original drawing region.
|
||||
GcSnapshot snapshot = Canvas_Delegate.getDelegate(canvas).getSnapshot();
|
||||
Rectangle originalClip = snapshot.getOriginalClip();
|
||||
if (originalClip != null) {
|
||||
canvas.clipRect(originalClip.x, originalClip.y, originalClip.x + originalClip.width,
|
||||
originalClip.y + originalClip.height, Op.REPLACE);
|
||||
canvas.clipRect(-canvas.getWidth(), -canvas.getHeight(), canvas.getWidth(),
|
||||
canvas.getHeight(), Op.INTERSECT);
|
||||
}
|
||||
canvas.translate(0, shadowSize / 2f);
|
||||
return saved;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.NoninvertibleTransformException;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
@@ -870,4 +871,33 @@ public class GcSnapshot {
|
||||
dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the clip of the oldest snapshot of the stack, appropriately translated to be
|
||||
* expressed in the coordinate system of the latest snapshot.
|
||||
*/
|
||||
public Rectangle getOriginalClip() {
|
||||
GcSnapshot originalSnapshot = this;
|
||||
while (originalSnapshot.mPrevious != null) {
|
||||
originalSnapshot = originalSnapshot.mPrevious;
|
||||
}
|
||||
if (originalSnapshot.mLayers.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Graphics2D graphics2D = originalSnapshot.mLayers.get(0).getGraphics();
|
||||
Rectangle bounds = graphics2D.getClipBounds();
|
||||
if (bounds == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
AffineTransform originalTransform =
|
||||
((Graphics2D) graphics2D.create()).getTransform().createInverse();
|
||||
AffineTransform latestTransform = getTransform().createInverse();
|
||||
bounds.x += latestTransform.getTranslateX() - originalTransform.getTranslateX();
|
||||
bounds.y += latestTransform.getTranslateY() - originalTransform.getTranslateY();
|
||||
} catch (NoninvertibleTransformException e) {
|
||||
Bridge.getLog().warning(null, "Non invertible transformation", null);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user