diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowCanvasTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowCanvasTest.java index 9099bc79ca6..730cabe90d3 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowCanvasTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowCanvasTest.java @@ -38,29 +38,36 @@ public void shouldDescribeBitmapDrawing() throws Exception { canvas.drawBitmap(imageBitmap, 1, 2, new Paint()); canvas.drawBitmap(imageBitmap, 100, 200, new Paint()); - assertEquals("Bitmap for file:/an/image.jpg at (1,2)\n" + - "Bitmap for file:/an/image.jpg at (100,200)", shadowOf(canvas).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg at (1,2)\n" + "Bitmap for file:/an/image.jpg at (100,200)", + shadowOf(canvas).getDescription()); - assertEquals("Bitmap for file:/an/image.jpg at (1,2)\n" + - "Bitmap for file:/an/image.jpg at (100,200)", shadowOf(targetBitmap).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg at (1,2)\n" + "Bitmap for file:/an/image.jpg at (100,200)", + shadowOf(targetBitmap).getDescription()); } @Test public void shouldDescribeBitmapDrawing_withDestinationRect() throws Exception { Canvas canvas = new Canvas(targetBitmap); - canvas.drawBitmap(imageBitmap, new Rect(1,2,3,4), new Rect(5,6,7,8), new Paint()); + canvas.drawBitmap(imageBitmap, new Rect(1, 2, 3, 4), new Rect(5, 6, 7, 8), new Paint()); - assertEquals("Bitmap for file:/an/image.jpg at (5,6) with height=2 and width=2 taken from" - + " Rect(1, 2 - 3, 4)", shadowOf(canvas).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg at (5,6) with height=2 and width=2 taken from" + + " Rect(1, 2 - 3, 4)", + shadowOf(canvas).getDescription()); } @Test public void shouldDescribeBitmapDrawing_withDestinationRectF() throws Exception { Canvas canvas = new Canvas(targetBitmap); - canvas.drawBitmap(imageBitmap, new Rect(1,2,3,4), new RectF(5.0f,6.0f,7.5f,8.5f), new Paint()); + canvas.drawBitmap( + imageBitmap, new Rect(1, 2, 3, 4), new RectF(5.0f, 6.0f, 7.5f, 8.5f), new Paint()); - assertEquals("Bitmap for file:/an/image.jpg at (5.0,6.0) with height=2.5 and width=2.5 taken" - + " from Rect(1, 2 - 3, 4)", shadowOf(canvas).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg at (5.0,6.0) with height=2.5 and width=2.5 taken" + + " from Rect(1, 2 - 3, 4)", + shadowOf(canvas).getDescription()); } @Test @@ -69,13 +76,17 @@ public void shouldDescribeBitmapDrawing_WithMatrix() throws Exception { canvas.drawBitmap(imageBitmap, new Matrix(), new Paint()); canvas.drawBitmap(imageBitmap, new Matrix(), new Paint()); - assertEquals("Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" - + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," - + " post=[]]", shadowOf(canvas).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" + + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," + + " post=[]]", + shadowOf(canvas).getDescription()); - assertEquals("Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" - + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," - + " post=[]]", shadowOf(targetBitmap).getDescription()); + assertEquals( + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" + + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," + + " post=[]]", + shadowOf(targetBitmap).getDescription()); } @Test @@ -84,10 +95,11 @@ public void visualize_shouldReturnDescription() throws Exception { canvas.drawBitmap(imageBitmap, new Matrix(), new Paint()); canvas.drawBitmap(imageBitmap, new Matrix(), new Paint()); - assertEquals("Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" - + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," - + " post=[]]", ShadowCanvas.visualize(canvas)); - + assertEquals( + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}, post=[]]\n" + + "Bitmap for file:/an/image.jpg transformed by Matrix[pre=[], set={}," + + " post=[]]", + ShadowCanvas.visualize(canvas)); } @Test @@ -96,8 +108,8 @@ public void drawColor_shouldReturnDescription() throws Exception { canvas.drawColor(Color.WHITE); canvas.drawColor(Color.GREEN); canvas.drawColor(Color.TRANSPARENT); - assertEquals("draw color -1draw color -16711936draw color 0", - shadowOf(canvas).getDescription()); + assertEquals( + "draw color -1draw color -16711936draw color 0", shadowOf(canvas).getDescription()); } @Test @@ -125,7 +137,8 @@ public void drawPath_shouldRecordThePathAndThePaint() throws Exception { } @Test - public void drawPath_shouldRecordThePointsOfEachPathEvenWhenItIsTheSameInstance() throws Exception { + public void drawPath_shouldRecordThePointsOfEachPathEvenWhenItIsTheSameInstance() + throws Exception { Canvas canvas = new Canvas(targetBitmap); Paint paint = new Paint(); Path path = new Path(); @@ -139,8 +152,10 @@ public void drawPath_shouldRecordThePointsOfEachPathEvenWhenItIsTheSameInstance( ShadowCanvas shadow = shadowOf(canvas); assertThat(shadow.getPathPaintHistoryCount()).isEqualTo(2); - assertEquals(shadowOf(shadow.getDrawnPath(0)).getPoints().get(0), new ShadowPath.Point(10, 10, LINE_TO)); - assertEquals(shadowOf(shadow.getDrawnPath(1)).getPoints().get(0), new ShadowPath.Point(20, 20, LINE_TO)); + assertEquals( + shadowOf(shadow.getDrawnPath(0)).getPoints().get(0), new ShadowPath.Point(10, 10, LINE_TO)); + assertEquals( + shadowOf(shadow.getDrawnPath(1)).getPoints().get(0), new ShadowPath.Point(20, 20, LINE_TO)); } @Test @@ -157,8 +172,13 @@ public void drawPath_shouldAppendDescriptionToBitmap() throws Exception { canvas.drawPath(path1, paint); canvas.drawPath(path2, paint); - assertEquals("Path " + shadowOf(path1).getPoints().toString() + "\n" - + "Path " + shadowOf(path2).getPoints().toString(), shadowOf(canvas).getDescription()); + assertEquals( + "Path " + + shadowOf(path1).getPoints().toString() + + "\n" + + "Path " + + shadowOf(path2).getPoints().toString(), + shadowOf(canvas).getDescription()); assertEquals( "Path " @@ -223,7 +243,7 @@ public void shouldRecordText_charArrayOverload() throws Exception { Canvas canvas = new Canvas(); Paint paint = new Paint(); paint.setColor(1); - canvas.drawText(new char[]{'h', 'e', 'l', 'l', 'o'}, 2, 3, 1f, 2f, paint); + canvas.drawText(new char[] {'h', 'e', 'l', 'l', 'o'}, 2, 3, 1f, 2f, paint); ShadowCanvas shadowCanvas = shadowOf(canvas); assertThat(shadowCanvas.getTextHistoryCount()).isEqualTo(1); @@ -529,4 +549,37 @@ public void restoreToCount() { assertThat(canvas.getSaveCount()).isEqualTo(save1); } + + @Test + public void drawRect_withPureFloatPosition() { + Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); + bitmap.eraseColor(Color.BLACK); + assertThat(bitmap.getPixel(0, 0)).isEqualTo(Color.BLACK); + + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + paint.setAntiAlias(true); + paint.setColor(Color.WHITE); + canvas.drawRect(0, 0, 10, 10, paint); + assertThat(bitmap.getPixel(0, 0)).isEqualTo(Color.WHITE); + } + + @Test + public void drawRect_withRectF() throws Exception { + Canvas canvas = new Canvas(); + Paint paint = new Paint(); + paint.setColor(Color.WHITE); + RectF rect = new RectF(2f, 4f, 10f, 10f); + canvas.drawRect(2f, 4f, 10f, 10f, paint); + ShadowCanvas shadowCanvas = shadowOf(canvas); + + ShadowCanvas.RectPaintHistoryEvent drawRect = shadowCanvas.getDrawnRect(0); + assertThat(drawRect.left).isEqualTo(2f); + assertThat(drawRect.top).isEqualTo(4f); + assertThat(drawRect.right).isEqualTo(10f); + assertThat(drawRect.bottom).isEqualTo(10f); + assertThat(drawRect.rect).isEqualTo(rect); + assertThat(drawRect.paint.getColor()).isEqualTo(Color.WHITE); + } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBitmap.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBitmap.java index 4c4a7e2df81..9baa552dbbb 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBitmap.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBitmap.java @@ -20,6 +20,9 @@ import android.os.Build; import android.os.Parcel; import android.util.DisplayMetrics; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBufferInt; @@ -45,14 +48,12 @@ public class ShadowBitmap { /** Number of bytes used internally to represent each pixel */ private static final int INTERNAL_BYTES_PER_PIXEL = 4; - @RealObject - private Bitmap realBitmap; - int createdFromResId = -1; String createdFromPath; InputStream createdFromStream; FileDescriptor createdFromFileDescriptor; byte[] createdFromBytes; + @RealObject private Bitmap realBitmap; private Bitmap createdFromBitmap; private Bitmap scaledFromBitmap; private int createdFromX = -1; @@ -86,126 +87,6 @@ public static String visualize(Bitmap bitmap) { return shadowBitmap.getDescription(); } - /** - * Reference to original Bitmap from which this Bitmap was created. {@code null} if this Bitmap - * was not copied from another instance. - * - * @return Original Bitmap from which this Bitmap was created. - */ - public Bitmap getCreatedFromBitmap() { - return createdFromBitmap; - } - - /** - * Resource ID from which this Bitmap was created. {@code 0} if this Bitmap was not created - * from a resource. - * - * @return Resource ID from which this Bitmap was created. - */ - public int getCreatedFromResId() { - return createdFromResId; - } - - /** - * Path from which this Bitmap was created. {@code null} if this Bitmap was not create from a - * path. - * - * @return Path from which this Bitmap was created. - */ - public String getCreatedFromPath() { - return createdFromPath; - } - - /** - * {@link InputStream} from which this Bitmap was created. {@code null} if this Bitmap was not - * created from a stream. - * - * @return InputStream from which this Bitmap was created. - */ - public InputStream getCreatedFromStream() { - return createdFromStream; - } - - /** - * Bytes from which this Bitmap was created. {@code null} if this Bitmap was not created from - * bytes. - * - * @return Bytes from which this Bitmap was created. - */ - public byte[] getCreatedFromBytes() { - return createdFromBytes; - } - - /** - * Horizontal offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. - * - * @return Horizontal offset within {@link #getCreatedFromBitmap()}. - */ - public int getCreatedFromX() { - return createdFromX; - } - - /** - * Vertical offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. - * - * @return Vertical offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. - */ - public int getCreatedFromY() { - return createdFromY; - } - - /** - * Width from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's - * content, or -1. - * - * @return Width from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's - * content, or -1. - */ - public int getCreatedFromWidth() { - return createdFromWidth; - } - - /** - * Height from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's - * content, or -1. - * @return Height from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's - * content, or -1. - */ - public int getCreatedFromHeight() { - return createdFromHeight; - } - - /** - * Color array from which this Bitmap was created. {@code null} if this Bitmap was not created - * from a color array. - * @return Color array from which this Bitmap was created. - */ - public int[] getCreatedFromColors() { - return createdFromColors; - } - - /** - * Matrix from which this Bitmap's content was transformed, or {@code null}. - * @return Matrix from which this Bitmap's content was transformed, or {@code null}. - */ - public Matrix getCreatedFromMatrix() { - return createdFromMatrix; - } - - /** - * {@code true} if this Bitmap was created with filtering. - * @return {@code true} if this Bitmap was created with filtering. - */ - public boolean getCreatedFromFilter() { - return createdFromFilter; - } - - @Implementation - protected boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream) { - appendDescription(" compressed as " + format + " with quality " + quality); - return ImageUtil.writeToStream(realBitmap, format, quality, stream); - } - @Implementation protected static Bitmap createBitmap(int width, int height, Bitmap.Config config) { return createBitmap((DisplayMetrics) null, width, height, config); @@ -427,6 +308,162 @@ protected static Bitmap createScaledBitmap( return scaledBitmap; } + @Implementation + protected static Bitmap nativeCreateFromParcel(Parcel p) { + int parceledWidth = p.readInt(); + int parceledHeight = p.readInt(); + Bitmap.Config parceledConfig = (Bitmap.Config) p.readSerializable(); + + int[] parceledColors = new int[parceledHeight * parceledWidth]; + p.readIntArray(parceledColors); + + return createBitmap( + parceledColors, 0, parceledWidth, parceledWidth, parceledHeight, parceledConfig); + } + + public static int getBytesPerPixel(Bitmap.Config config) { + if (config == null) { + throw new NullPointerException("Bitmap config was null."); + } + switch (config) { + case RGBA_F16: + return 8; + case ARGB_8888: + return 4; + case RGB_565: + case ARGB_4444: + return 2; + case ALPHA_8: + return 1; + default: + throw new IllegalArgumentException("Unknown bitmap config: " + config); + } + } + + /** + * Reference to original Bitmap from which this Bitmap was created. {@code null} if this Bitmap + * was not copied from another instance. + * + * @return Original Bitmap from which this Bitmap was created. + */ + public Bitmap getCreatedFromBitmap() { + return createdFromBitmap; + } + + /** + * Resource ID from which this Bitmap was created. {@code 0} if this Bitmap was not created from a + * resource. + * + * @return Resource ID from which this Bitmap was created. + */ + public int getCreatedFromResId() { + return createdFromResId; + } + + /** + * Path from which this Bitmap was created. {@code null} if this Bitmap was not create from a + * path. + * + * @return Path from which this Bitmap was created. + */ + public String getCreatedFromPath() { + return createdFromPath; + } + + /** + * {@link InputStream} from which this Bitmap was created. {@code null} if this Bitmap was not + * created from a stream. + * + * @return InputStream from which this Bitmap was created. + */ + public InputStream getCreatedFromStream() { + return createdFromStream; + } + + /** + * Bytes from which this Bitmap was created. {@code null} if this Bitmap was not created from + * bytes. + * + * @return Bytes from which this Bitmap was created. + */ + public byte[] getCreatedFromBytes() { + return createdFromBytes; + } + + /** + * Horizontal offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. + * + * @return Horizontal offset within {@link #getCreatedFromBitmap()}. + */ + public int getCreatedFromX() { + return createdFromX; + } + + /** + * Vertical offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. + * + * @return Vertical offset within {@link #getCreatedFromBitmap()} of this Bitmap's content, or -1. + */ + public int getCreatedFromY() { + return createdFromY; + } + + /** + * Width from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's + * content, or -1. + * + * @return Width from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this + * Bitmap's content, or -1. + */ + public int getCreatedFromWidth() { + return createdFromWidth; + } + + /** + * Height from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this Bitmap's + * content, or -1. + * + * @return Height from {@link #getCreatedFromX()} within {@link #getCreatedFromBitmap()} of this + * Bitmap's content, or -1. + */ + public int getCreatedFromHeight() { + return createdFromHeight; + } + + /** + * Color array from which this Bitmap was created. {@code null} if this Bitmap was not created + * from a color array. + * + * @return Color array from which this Bitmap was created. + */ + public int[] getCreatedFromColors() { + return createdFromColors; + } + + /** + * Matrix from which this Bitmap's content was transformed, or {@code null}. + * + * @return Matrix from which this Bitmap's content was transformed, or {@code null}. + */ + public Matrix getCreatedFromMatrix() { + return createdFromMatrix; + } + + /** + * {@code true} if this Bitmap was created with filtering. + * + * @return {@code true} if this Bitmap was created with filtering. + */ + public boolean getCreatedFromFilter() { + return createdFromFilter; + } + + @Implementation + protected boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream) { + appendDescription(" compressed as " + format + " with quality " + quality); + return ImageUtil.writeToStream(realBitmap, format, quality, stream); + } + @Implementation protected void setPixels( int[] pixels, int offset, int stride, int x, int y, int width, int height) { @@ -543,14 +580,14 @@ public void appendDescription(String s) { description += s; } - public void setDescription(String s) { - description = s; - } - public String getDescription() { return description; } + public void setDescription(String s) { + description = s; + } + @Implementation protected final boolean hasAlpha() { return hasAlpha && config != Config.RGB_565; @@ -588,19 +625,14 @@ protected final void setHasMipMap(boolean hasMipMap) { this.hasMipMap = hasMipMap; } - @Implementation(minSdk = KITKAT) - protected void setWidth(int width) { - this.width = width; - } - @Implementation protected int getWidth() { return width; } @Implementation(minSdk = KITKAT) - protected void setHeight(int height) { - this.height = height; + protected void setWidth(int width) { + this.width = width; } @Implementation @@ -608,6 +640,11 @@ protected int getHeight() { return height; } + @Implementation(minSdk = KITKAT) + protected void setHeight(int height) { + this.height = height; + } + @Implementation protected int getGenerationId() { return 0; @@ -640,20 +677,6 @@ protected void writeToParcel(Parcel p, int flags) { p.writeIntArray(pixels); } - - @Implementation - protected static Bitmap nativeCreateFromParcel(Parcel p) { - int parceledWidth = p.readInt(); - int parceledHeight = p.readInt(); - Bitmap.Config parceledConfig = (Bitmap.Config) p.readSerializable(); - - int[] parceledColors = new int[parceledHeight * parceledWidth]; - p.readIntArray(parceledColors); - - return createBitmap( - parceledColors, 0, parceledWidth, parceledWidth, parceledHeight, parceledConfig); - } - @Implementation protected void copyPixelsFromBuffer(Buffer dst) { if (isRecycled()) { @@ -662,7 +685,9 @@ protected void copyPixelsFromBuffer(Buffer dst) { // See the related comment in #copyPixelsToBuffer(Buffer). if (getBytesPerPixel(config) != INTERNAL_BYTES_PER_PIXEL) { - throw new RuntimeException("Not implemented: only Bitmaps with " + INTERNAL_BYTES_PER_PIXEL + throw new RuntimeException( + "Not implemented: only Bitmaps with " + + INTERNAL_BYTES_PER_PIXEL + " bytes per pixel are supported"); } if (!(dst instanceof ByteBuffer) && !(dst instanceof IntBuffer)) { @@ -698,7 +723,9 @@ protected void copyPixelsToBuffer(Buffer dst) { // getByteCount(), but if we don't enforce this restriction then for RGB_4444 and other // configs that value would be smaller then the buffer size we actually need. if (getBytesPerPixel(config) != INTERNAL_BYTES_PER_PIXEL) { - throw new RuntimeException("Not implemented: only Bitmaps with " + INTERNAL_BYTES_PER_PIXEL + throw new RuntimeException( + "Not implemented: only Bitmaps with " + + INTERNAL_BYTES_PER_PIXEL + " bytes per pixel are supported"); } @@ -732,13 +759,13 @@ protected void reconfigure(int width, int height, Bitmap.Config config) { } @Implementation(minSdk = KITKAT) - protected void setPremultiplied(boolean isPremultiplied) { - this.requestPremultiplied = isPremultiplied; + protected boolean isPremultiplied() { + return requestPremultiplied && hasAlpha(); } @Implementation(minSdk = KITKAT) - protected boolean isPremultiplied() { - return requestPremultiplied && hasAlpha(); + protected void setPremultiplied(boolean isPremultiplied) { + this.requestPremultiplied = isPremultiplied; } @Implementation(minSdk = O) @@ -790,25 +817,6 @@ public Bitmap getRealBitmap() { return realBitmap; } - public static int getBytesPerPixel(Bitmap.Config config) { - if (config == null) { - throw new NullPointerException("Bitmap config was null."); - } - switch (config) { - case RGBA_F16: - return 8; - case ARGB_8888: - return 4; - case RGB_565: - case ARGB_4444: - return 2; - case ALPHA_8: - return 1; - default: - throw new IllegalArgumentException("Unknown bitmap config: " + config); - } - } - public void setCreatedFromResId(int resId, String description) { this.createdFromResId = resId; appendDescription(" for resource:" + description); @@ -856,6 +864,18 @@ void drawRect(Rect r, Paint paint) { } } + void drawRect(RectF r, Paint paint) { + if (bufferedImage == null) { + return; + } + + Graphics2D graphics2D = bufferedImage.createGraphics(); + Rectangle2D r2d = new Rectangle2D.Float(r.left, r.top, r.right - r.left, r.bottom - r.top); + graphics2D.setColor(new Color(paint.getColor())); + graphics2D.draw(r2d); + graphics2D.dispose(); + } + void drawBitmap(Bitmap source, int left, int top) { ShadowBitmap shadowSource = Shadows.shadowOf(source); if (bufferedImage == null || shadowSource.bufferedImage == null) { @@ -892,11 +912,11 @@ void drawBitmap(Bitmap source, int left, int top) { } } - void setBufferedImage(BufferedImage bufferedImage) { - this.bufferedImage = bufferedImage; - } - BufferedImage getBufferedImage() { return bufferedImage; } + + void setBufferedImage(BufferedImage bufferedImage) { + this.bufferedImage = bufferedImage; + } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCanvas.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCanvas.java index 83dc4c70bb3..aa29d932d90 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCanvas.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCanvas.java @@ -39,9 +39,9 @@ import org.robolectric.util.reflector.ForType; /** - * Broken. This implementation is very specific to the application for which it was developed. - * Todo: Reimplement. Consider using the same strategy of collecting a history of draw events - * and providing methods for writing queries based on type, number, and order of events. + * Broken. This implementation is very specific to the application for which it was developed. Todo: + * Reimplement. Consider using the same strategy of collecting a history of draw events and + * providing methods for writing queries based on type, number, and order of events. */ @SuppressWarnings({"UnusedDeclaration"}) @Implements(Canvas.class) @@ -168,7 +168,7 @@ protected void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { int y = (int) (top + translateY); if (x != 0 || y != 0) { appendDescription(" at (" + x + "," + y + ")"); - } + } if (scaleX != 1 && scaleY != 1) { appendDescription(" scaled by (" + scaleX + "," + scaleY + ")"); @@ -186,12 +186,19 @@ protected void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { StringBuilder descriptionBuilder = new StringBuilder(); if (dst != null) { - descriptionBuilder.append(" at (").append(dst.left).append(",").append(dst.top) - .append(") with height=").append(dst.height()).append(" and width=").append(dst.width()); + descriptionBuilder + .append(" at (") + .append(dst.left) + .append(",") + .append(dst.top) + .append(") with height=") + .append(dst.height()) + .append(" and width=") + .append(dst.width()); } if (src != null) { - descriptionBuilder.append( " taken from ").append(src.toString()); + descriptionBuilder.append(" taken from ").append(src.toString()); } appendDescription(descriptionBuilder.toString()); } @@ -202,12 +209,19 @@ protected void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { StringBuilder descriptionBuilder = new StringBuilder(); if (dst != null) { - descriptionBuilder.append(" at (").append(dst.left).append(",").append(dst.top) - .append(") with height=").append(dst.height()).append(" and width=").append(dst.width()); + descriptionBuilder + .append(" at (") + .append(dst.left) + .append(",") + .append(dst.top) + .append(") with height=") + .append(dst.height()) + .append(" and width=") + .append(dst.width()); } if (src != null) { - descriptionBuilder.append( " taken from ").append(src.toString()); + descriptionBuilder.append(" taken from ").append(src.toString()); } appendDescription(descriptionBuilder.toString()); } @@ -243,6 +257,11 @@ protected void drawArc( @Implementation protected void drawRect(float left, float top, float right, float bottom, Paint paint) { rectPaintEvents.add(new RectPaintHistoryEvent(left, top, right, bottom, paint)); + + if (targetBitmap != null) { + ShadowBitmap shadowTargetBitmap = Shadows.shadowOf(targetBitmap); + shadowTargetBitmap.drawRect(new RectF(left, top, right, bottom), paint); + } } @Implementation @@ -608,8 +627,7 @@ public static class RectPaintHistoryEvent { public final float right; public final float bottom; - private RectPaintHistoryEvent( - float left, float top, float right, float bottom, Paint paint){ + private RectPaintHistoryEvent(float left, float top, float right, float bottom, Paint paint) { this.rect = new RectF(left, top, right, bottom); this.paint = new Paint(paint); this.paint.setColor(paint.getColor()); @@ -682,8 +700,8 @@ public static class ArcPaintHistoryEvent { public final boolean useCenter; public final Paint paint; - public ArcPaintHistoryEvent(RectF oval, float startAngle, float sweepAngle, boolean useCenter, - Paint paint) { + public ArcPaintHistoryEvent( + RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) { this.oval = oval; this.startAngle = startAngle; this.sweepAngle = sweepAngle;