Loading tools/layoutlib/bridge/src/android/view/RectShadowPainter.java +13 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.view; package android.view; import com.android.layoutlib.bridge.impl.GcSnapshot; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.layoutlib.bridge.impl.ResourceHelper; import android.graphics.Canvas; import android.graphics.Canvas; Loading @@ -32,6 +33,8 @@ import android.graphics.RectF; import android.graphics.Region.Op; import android.graphics.Region.Op; import android.graphics.Shader.TileMode; import android.graphics.Shader.TileMode; import java.awt.Rectangle; /** /** * Paints shadow for rounded rectangles. Inspiration from CardView. Couldn't use that directly, * 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. * since it modifies the size of the content, that we can't do. Loading Loading @@ -127,9 +130,16 @@ public class RectShadowPainter { int saved = canvas.save(); int saved = canvas.save(); // Usually canvas has been translated to the top left corner of the view when this is // 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. // 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. // 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.clipRect(-canvas.getWidth(), -canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), Op.REPLACE); canvas.getHeight(), Op.INTERSECT); } canvas.translate(0, shadowSize / 2f); canvas.translate(0, shadowSize / 2f); return saved; return saved; } } Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +30 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.Area; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.ArrayList; Loading Loading @@ -870,4 +871,33 @@ public class GcSnapshot { dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); 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; } } } Loading
tools/layoutlib/bridge/src/android/view/RectShadowPainter.java +13 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.view; package android.view; import com.android.layoutlib.bridge.impl.GcSnapshot; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.layoutlib.bridge.impl.ResourceHelper; import android.graphics.Canvas; import android.graphics.Canvas; Loading @@ -32,6 +33,8 @@ import android.graphics.RectF; import android.graphics.Region.Op; import android.graphics.Region.Op; import android.graphics.Shader.TileMode; import android.graphics.Shader.TileMode; import java.awt.Rectangle; /** /** * Paints shadow for rounded rectangles. Inspiration from CardView. Couldn't use that directly, * 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. * since it modifies the size of the content, that we can't do. Loading Loading @@ -127,9 +130,16 @@ public class RectShadowPainter { int saved = canvas.save(); int saved = canvas.save(); // Usually canvas has been translated to the top left corner of the view when this is // 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. // 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. // 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.clipRect(-canvas.getWidth(), -canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), Op.REPLACE); canvas.getHeight(), Op.INTERSECT); } canvas.translate(0, shadowSize / 2f); canvas.translate(0, shadowSize / 2f); return saved; return saved; } } Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +30 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.Area; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.ArrayList; Loading Loading @@ -870,4 +871,33 @@ public class GcSnapshot { dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); 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; } } }