133873d2b41a5cd2597b20a4e88eb8942944c0f23Tyler Schultzpackage com.xtremelabs.robolectric.shadows;
256a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard
331690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richardimport android.graphics.*;
422c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implementation;
522c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implements;
656a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard
732c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richardimport java.util.ArrayList;
832c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richardimport java.util.List;
932c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
1022ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwinimport static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
11e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williamsimport static com.xtremelabs.robolectric.Robolectric.shadowOf;
12e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams
13fa51ab3a5a2a5f25dfc223e8a37d0f8002d757bfPhil Goodwin/**
1433040bdd7715a46bfcfe3cc5f894972ef65d31beChristian Williams * Shadows the {@code android.graphics.Canvas} class.
15580676cf93d673bf5ad0328f261f6980cfec6f61Josh Lauer & Christian Williams * <p/>
16fa51ab3a5a2a5f25dfc223e8a37d0f8002d757bfPhil Goodwin * Broken.
17fa51ab3a5a2a5f25dfc223e8a37d0f8002d757bfPhil Goodwin * This implementation is very specific to the application for which it was developed.
18fa51ab3a5a2a5f25dfc223e8a37d0f8002d757bfPhil Goodwin * 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.
19fa51ab3a5a2a5f25dfc223e8a37d0f8002d757bfPhil Goodwin */
2056a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard@SuppressWarnings({"UnusedDeclaration"})
2156a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard@Implements(Canvas.class)
22afe0a89d904a7fe2f5980b9deb26cc3240192459Christian Williamspublic class ShadowCanvas {
238163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    private List<PathPaintHistoryEvent> pathPaintEvents = new ArrayList<PathPaintHistoryEvent>();
248163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    private List<CirclePaintHistoryEvent> circlePaintEvents = new ArrayList<CirclePaintHistoryEvent>();
25cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    private Paint drawnPaint;
2622ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin    private Bitmap targetBitmap = newInstanceOf(Bitmap.class);
270d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams    private float translateX;
280d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams    private float translateY;
29d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    private float scaleX = 1;
30d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    private float scaleY = 1;
3156a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard
322b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams    public void __constructor__(Bitmap bitmap) {
3322ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        this.targetBitmap = bitmap;
342b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams    }
352b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams
36e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    public void appendDescription(String s) {
3722ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        shadowOf(targetBitmap).appendDescription(s);
38e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    }
39e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams
40e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    public String getDescription() {
4122ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        return shadowOf(targetBitmap).getDescription();
42e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    }
43e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams
44de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
450d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams    public void translate(float x, float y) {
460d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        this.translateX = x;
470d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        this.translateY = y;
480d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams    }
490d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams
500d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams    @Implementation
51d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    public void scale(float sx, float sy) {
52d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        this.scaleX = sx;
53d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        this.scaleY = sy;
54d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    }
55d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams
56d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    @Implementation
57d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    public void scale(float sx, float sy, float px, float py) {
58d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        this.scaleX = sx;
59d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        this.scaleY = sy;
60d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams    }
6156a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard
62de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
6393a1ab50e8a7374d3f500c45052ddad66726c923Joe Moore & Phil Goodwin    public void drawPaint(Paint paint) {
6493a1ab50e8a7374d3f500c45052ddad66726c923Joe Moore & Phil Goodwin        drawnPaint = paint;
6593a1ab50e8a7374d3f500c45052ddad66726c923Joe Moore & Phil Goodwin    }
66a308660ae43088e6571467e5d34ff41c5045436bMike Grafton
67b19eb0e5038b72cc7460536f408d22721ec0a4e8Michael Portuesi    @Implementation
68b19eb0e5038b72cc7460536f408d22721ec0a4e8Michael Portuesi    public void drawColor(int color) {
69a308660ae43088e6571467e5d34ff41c5045436bMike Grafton        appendDescription("draw color " + color);
70b19eb0e5038b72cc7460536f408d22721ec0a4e8Michael Portuesi    }
7193a1ab50e8a7374d3f500c45052ddad66726c923Joe Moore & Phil Goodwin
72de9feed5ddf1d91a3e76cbc71712c36a7652201eChristian Williams    @Implementation
73e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
7422ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        describeBitmap(bitmap, paint);
750d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams
760d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        int x = (int) (left + translateX);
770d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        int y = (int) (top + translateY);
780d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        if (x != 0 && y != 0) {
790d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams            appendDescription(" at (" + x + "," + y + ")");
800d21afe8a769457a7c6691bd8418a73aafb46beaJosh Lauer & Christian Williams        }
81d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams
82d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        if (scaleX != 1 && scaleY != 1) {
83d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams            appendDescription(" scaled by (" + scaleX + "," + scaleY + ")");
84d4e5d32b81cae2114f66739beaac6fe1ceeead0dJosh Lauer & Christian Williams        }
852b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams    }
862b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams
87a308660ae43088e6571467e5d34ff41c5045436bMike Grafton    @Implementation
88a308660ae43088e6571467e5d34ff41c5045436bMike Grafton    public void drawPath(Path path, Paint paint) {
89a308660ae43088e6571467e5d34ff41c5045436bMike Grafton        pathPaintEvents.add(new PathPaintHistoryEvent(path, paint));
9031690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard
9131690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard        separateLines();
9231690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard        appendDescription("Path " + shadowOf(path).getPoints().toString());
93a308660ae43088e6571467e5d34ff41c5045436bMike Grafton    }
94a308660ae43088e6571467e5d34ff41c5045436bMike Grafton
9522ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin    private void describeBitmap(Bitmap bitmap, Paint paint) {
9631690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard        separateLines();
972b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams
9822ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        appendDescription(shadowOf(bitmap).getDescription());
9922ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin
1002b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams        if (paint != null) {
1012b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams            ColorFilter colorFilter = paint.getColorFilter();
1022b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams            if (colorFilter != null) {
1032b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams                appendDescription(" with " + colorFilter);
1042b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams            }
1052b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams        }
10622ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin    }
1072b1c0603c5d232bfe77ba6eb22f3cf30bb913869Josh Lauer & Christian Williams
10831690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard    private void separateLines() {
10931690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard        if (getDescription().length() != 0) {
11031690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard            appendDescription("\n");
11131690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard        }
11231690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard    }
11331690e8cb538efe3141638d6657db4c2621d3429Aaron VonderHaar & Ryan Richard
11422ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin    @Implementation
11522ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
11622ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        describeBitmap(bitmap, paint);
117580676cf93d673bf5ad0328f261f6980cfec6f61Josh Lauer & Christian Williams
11822ae0c422c4f1bb6878f624fbf2531eea4da0187Christian Williams & Phil Goodwin        appendDescription(" transformed by matrix");
119e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams    }
120e3bf0c0e84dd3464de0a508f9c03512d23c11bd8Josh Lauer & Christian Williams
1218163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    public int getPathPaintHistoryCount() {
12232c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        return pathPaintEvents.size();
12332c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    }
12432c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
1258163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    public int getCirclePaintHistoryCount() {
1268163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        return circlePaintEvents.size();
1278163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    }
1288163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard
12932c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    public boolean hasDrawnPath() {
1308163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        return getPathPaintHistoryCount() > 0;
13132c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    }
13232c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
13332c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    public boolean hasDrawnCircle() {
1348163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        return circlePaintEvents.size() > 0;
13532c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    }
13632c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
13732c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    public Paint getDrawnPathPaint(int i) {
13832c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        return pathPaintEvents.get(i).pathPaint;
13932c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    }
14032c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
14132c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    public Path getDrawnPath(int i) {
14232c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        return pathPaintEvents.get(i).drawnPath;
14332c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard    }
14432c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
1458163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    public CirclePaintHistoryEvent getDrawnCircle(int i) {
1468163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        return circlePaintEvents.get(i);
1478163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    }
1488163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard
1498163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    public void resetCanvasHistory() {
1508163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        pathPaintEvents.clear();
1518163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        circlePaintEvents.clear();
1528163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    }
1538163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard
154cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    public Paint getDrawnPaint() {
155cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin        return drawnPaint;
156cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin    }
157cc54a84f7c9f42028529e545e50b043e83f53c1cChristian Williams & Phil Goodwin
1588163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    private static class PathPaintHistoryEvent {
15932c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        private Path drawnPath;
16032c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        private Paint pathPaint;
16132c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard
1628163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        PathPaintHistoryEvent(Path drawnPath, Paint pathPaint) {
16332c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard            this.drawnPath = drawnPath;
16432c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard            this.pathPaint = pathPaint;
16532c37ca6a61b1cee08c99fc206f8907c69905e23Chee Wong & Ryan Richard        }
16656a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard    }
1678163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard
1688163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    public static class CirclePaintHistoryEvent {
1698163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        public Paint paint;
1708163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        public float centerX;
1718163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        public float centerY;
1728163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        public float radius;
1738163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard
1748163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        private CirclePaintHistoryEvent(float centerX, float centerY, float radius, Paint paint) {
1758163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard            this.paint = paint;
1768163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard            this.centerX = centerX;
1778163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard            this.centerY = centerY;
1788163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard            this.radius = radius;
1798163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard        }
1808163d95a598814cfb4c9823d43a5a37c024b8d94Joe Moore & Ryan Richard    }
18156a2a9db15f97a56b5eacef4645bc8ba8790ba6cChee Wong & Ryan Richard}
182