Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 555fcd55 authored by Jerome Gaillard's avatar Jerome Gaillard
Browse files

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)
parent 5ce42bba
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -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.
        // 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.REPLACE);
              canvas.getHeight(), Op.INTERSECT);
        }
        canvas.translate(0, shadowSize / 2f);
        return saved;
    }
+30 −0
Original line number Diff line number Diff line
@@ -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;
    }

}