• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.O;
4 import static org.junit.Assert.assertEquals;
5 import static org.junit.Assert.assertTrue;
6 
7 import android.graphics.Bitmap;
8 import android.graphics.Canvas;
9 import android.graphics.Color;
10 import android.graphics.DiscretePathEffect;
11 import android.graphics.Paint;
12 import android.graphics.Paint.Style;
13 import android.graphics.Path;
14 import android.graphics.PorterDuff.Mode;
15 import android.graphics.PorterDuffXfermode;
16 import androidx.test.ext.junit.runners.AndroidJUnit4;
17 import org.junit.Test;
18 import org.junit.runner.RunWith;
19 import org.robolectric.annotation.Config;
20 
21 @RunWith(AndroidJUnit4.class)
22 @Config(minSdk = O)
23 public class ShadowNativeDiscretePathEffectTest {
24   private static final int BITMAP_WIDTH = 200;
25   private static final int BITMAP_HEIGHT = 100;
26   private static final int START_X = 10;
27   private static final int END_X = BITMAP_WIDTH - START_X;
28   private static final int COORD_Y = BITMAP_HEIGHT / 2;
29   private static final int SEGMENT_LENGTH = 10; // must be < BITMAP_WIDTH
30   private static final int DEVIATION = 10; // must be < BITMAP_HEIGHT
31 
32   @Test
testDiscretePathEffect()33   public void testDiscretePathEffect() {
34     DiscretePathEffect effect = new DiscretePathEffect(SEGMENT_LENGTH, DEVIATION);
35 
36     Paint paint = new Paint();
37     paint.setColor(Color.GREEN);
38     paint.setStyle(Style.STROKE);
39     paint.setStrokeWidth(0);
40     paint.setPathEffect(effect);
41     paint.setAntiAlias(false);
42 
43     Path path = new Path();
44     path.moveTo(START_X, COORD_Y);
45     path.lineTo(END_X, COORD_Y);
46 
47     Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_8888);
48     bitmap.eraseColor(Color.TRANSPARENT);
49 
50     Canvas canvas = new Canvas(bitmap);
51     canvas.drawPath(path, paint);
52 
53     // draw guide line into red channel (each segment should cross this once)
54     paint = new Paint();
55     paint.setColor(Color.RED);
56     paint.setStyle(Style.STROKE);
57     paint.setStrokeWidth(0);
58     paint.setXfermode(new PorterDuffXfermode(Mode.SCREEN));
59     canvas.drawPath(path, paint);
60 
61     // draw guide rectangle into blue channel (each segment must be completely inside this)
62     paint.setColor(Color.BLUE);
63     paint.setStrokeWidth(1 + 2 * DEVIATION);
64     canvas.drawPath(path, paint);
65 
66     int intersect = 0;
67     int numGreenPixels = 0;
68     int minY = BITMAP_HEIGHT;
69     int maxY = 0;
70     for (int y = 0; y < BITMAP_HEIGHT; y++) {
71       for (int x = 0; x < BITMAP_WIDTH; x++) {
72         int pixel = bitmap.getPixel(x, y);
73         if (Color.green(pixel) > 0) {
74           numGreenPixels += 1;
75           minY = Math.min(minY, y);
76           maxY = Math.max(maxY, y);
77           assertEquals(0xFF, Color.blue(pixel));
78           if (Color.red(pixel) > 0) {
79             intersect += 1;
80           }
81         }
82       }
83     }
84     int lineLength = END_X - START_X;
85     // the number of pixels in all segments must be at least the same as the line length
86     assertTrue(numGreenPixels >= lineLength);
87     // green line must vary in y direction
88     assertTrue(maxY - minY > 0);
89     // ... but not too much
90     assertTrue(maxY - minY <= 1 + 2 * DEVIATION);
91     // intersecting pixels must be less than line length, otherwise deviation doesn't work
92     assertTrue(intersect < lineLength);
93     // there must be at least as many intersecting pixels as there are full segments
94     assertTrue(intersect >= lineLength / SEGMENT_LENGTH);
95   }
96 }
97