Home | History | Annotate | Download | only in testclasses
      1 /*
      2 * Copyright (C) 2014 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 *      http://www.apache.org/licenses/LICENSE2.0
      9 *
     10 * Unless required by applicable law or agreed to in riting, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 package android.uirendering.cts.testclasses;
     17 
     18 import android.graphics.Bitmap;
     19 import android.graphics.Canvas;
     20 import android.graphics.Color;
     21 import android.graphics.LinearGradient;
     22 import android.graphics.Paint;
     23 import android.graphics.Point;
     24 import android.graphics.PorterDuff;
     25 import android.graphics.PorterDuffXfermode;
     26 import android.graphics.Rect;
     27 import android.graphics.RectF;
     28 import android.graphics.Shader;
     29 import android.test.suitebuilder.annotation.SmallTest;
     30 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
     31 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
     32 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
     33 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
     34 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
     35 import android.uirendering.cts.testinfrastructure.CanvasClient;
     36 import android.uirendering.cts.testinfrastructure.DisplayModifier;
     37 import android.uirendering.cts.testinfrastructure.ResourceModifier;
     38 
     39 import java.util.LinkedHashMap;
     40 import java.util.Map;
     41 
     42 /**
     43  * Test cases of all combination of resource modifications.
     44  */
     45 public class SweepTests extends ActivityTestBase {
     46     private static final String TAG = "SweepTests";
     47 
     48     public static final int BG_COLOR = 0xFFFFFFFF;
     49     public static final int DST_COLOR = 0xFFFFCC44;
     50     public static final int SRC_COLOR = 0xFF66AAFF;
     51     public static final int MULTIPLY_COLOR = 0xFF668844;
     52     public static final int SCREEN_COLOR = 0xFFFFEEFF;
     53 
     54     // These points are in pairs, the first being the lower left corner, the second is only in the
     55     // Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
     56     // the Source bitmap.
     57     private final static Point[] XFERMODE_TEST_POINTS = new Point[] {
     58             new Point(1, 80), new Point(25, 25), new Point(35, 35), new Point(70, 70)
     59     };
     60 
     61     /**
     62      * There are 4 locations we care about in any filter testing.
     63      *
     64      * 1) Both empty
     65      * 2) Only src, dst empty
     66      * 3) Both src + dst
     67      * 4) Only dst, src empty
     68      */
     69     private final Map<PorterDuff.Mode, int[]> XFERMODE_COLOR_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
     70         {
     71             put(PorterDuff.Mode.SRC, new int[] {
     72                     BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR
     73             });
     74 
     75             put(PorterDuff.Mode.DST, new int[] {
     76                     BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR
     77             });
     78 
     79             put(PorterDuff.Mode.SRC_OVER, new int[] {
     80                     BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR
     81             });
     82 
     83             put(PorterDuff.Mode.DST_OVER, new int[] {
     84                     BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR
     85             });
     86 
     87             put(PorterDuff.Mode.SRC_IN, new int[] {
     88                     BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR
     89             });
     90 
     91             put(PorterDuff.Mode.DST_IN, new int[] {
     92                     BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR
     93             });
     94 
     95             put(PorterDuff.Mode.SRC_OUT, new int[] {
     96                     BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR
     97             });
     98 
     99             put(PorterDuff.Mode.DST_OUT, new int[] {
    100                     BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR
    101             });
    102 
    103             put(PorterDuff.Mode.SRC_ATOP, new int[] {
    104                     BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR
    105             });
    106 
    107             put(PorterDuff.Mode.DST_ATOP, new int[] {
    108                     BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR
    109             });
    110 
    111             put(PorterDuff.Mode.XOR, new int[] {
    112                     BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR
    113             });
    114 
    115             put(PorterDuff.Mode.MULTIPLY, new int[] {
    116                     BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR
    117             });
    118 
    119             put(PorterDuff.Mode.SCREEN, new int[] {
    120                     BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR
    121             });
    122         }
    123     };
    124 
    125     private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
    126         private final RectF mSrcRect = new RectF(30, 30, 80, 80);
    127         private final RectF mDstRect = new RectF(10, 10, 60, 60);
    128         private final Bitmap mSrcBitmap = createSrc();
    129         private final Bitmap mDstBitmap = createDst();
    130 
    131         @Override
    132         public void modifyDrawing(Paint paint, Canvas canvas) {
    133             int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
    134 
    135             canvas.drawBitmap(mDstBitmap, 0, 0, null);
    136             canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
    137 
    138             canvas.restoreToCount(sc);
    139         }
    140 
    141         private Bitmap createSrc() {
    142             Bitmap srcB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
    143             Canvas srcCanvas = new Canvas(srcB);
    144             Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    145             srcPaint.setColor(SRC_COLOR);
    146             srcCanvas.drawRect(mSrcRect, srcPaint);
    147             return srcB;
    148         }
    149 
    150         private Bitmap createDst() {
    151             Bitmap dstB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
    152             Canvas dstCanvas = new Canvas(dstB);
    153             Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    154             dstPaint.setColor(DST_COLOR);
    155             dstCanvas.drawOval(mDstRect, dstPaint);
    156             return dstB;
    157         }
    158     };
    159 
    160     // We care about one point in each of the four rectangles of different alpha values, as well as
    161     // the area outside the rectangles
    162     private final static Point[] COLOR_FILTER_ALPHA_POINTS = new Point[] {
    163             new Point(9, 45),
    164             new Point(27, 45),
    165             new Point(45, 45),
    166             new Point(63, 45),
    167             new Point(81, 45)
    168     };
    169 
    170     public static final int FILTER_COLOR = 0xFFBB0000;
    171     private final Map<PorterDuff.Mode, int[]> COLOR_FILTER_ALPHA_MAP
    172             = new LinkedHashMap<PorterDuff.Mode, int[]>() {
    173         {
    174             put(PorterDuff.Mode.SRC, new int[] {
    175                     FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR
    176             });
    177 
    178             put(PorterDuff.Mode.DST, new int[] {
    179                     0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
    180             });
    181 
    182             put(PorterDuff.Mode.SRC_OVER, new int[] {
    183                     0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000
    184             });
    185 
    186             put(PorterDuff.Mode.DST_OVER, new int[] {
    187                     0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
    188             });
    189 
    190             put(PorterDuff.Mode.SRC_IN, new int[] {
    191                     0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF
    192             });
    193 
    194             put(PorterDuff.Mode.DST_IN, new int[] {
    195                     0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
    196             });
    197 
    198             put(PorterDuff.Mode.SRC_OUT, new int[] {
    199                     0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
    200             });
    201 
    202             put(PorterDuff.Mode.DST_OUT, new int[] {
    203                     0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
    204             });
    205 
    206             put(PorterDuff.Mode.SRC_ATOP, new int[] {
    207                     0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF
    208             });
    209 
    210             put(PorterDuff.Mode.DST_ATOP, new int[] {
    211                     0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
    212             });
    213 
    214             put(PorterDuff.Mode.XOR, new int[] {
    215                     0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
    216             });
    217 
    218             put(PorterDuff.Mode.MULTIPLY, new int[] {
    219                     0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF
    220             });
    221 
    222             put(PorterDuff.Mode.SCREEN, new int[] {
    223                     0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000
    224             });
    225         }
    226     };
    227 
    228     /**
    229      * Draws 5 blocks of different color/opacity to be blended against
    230      */
    231     private final static DisplayModifier COLOR_FILTER_ALPHA_MODIFIER = new DisplayModifier() {
    232         private final int[] BLOCK_COLORS = new int[] {
    233                 0x33808080,
    234                 0x66808080,
    235                 0x99808080,
    236                 0xCC808080,
    237                 0x00000000
    238         };
    239 
    240         private final Bitmap mBitmap = createQuadRectBitmap();
    241 
    242         public void modifyDrawing(Paint paint, Canvas canvas) {
    243             canvas.drawBitmap(mBitmap, 0, 0, paint);
    244         }
    245 
    246         private Bitmap createQuadRectBitmap() {
    247             Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
    248             Canvas canvas = new Canvas(bitmap);
    249             Paint paint = new Paint();
    250             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    251             final int blockCount = BLOCK_COLORS.length;
    252             final int blockWidth = TEST_WIDTH / blockCount;
    253             for (int i = 0 ; i < blockCount; i++) {
    254                 paint.setColor(BLOCK_COLORS[i]);
    255                 canvas.drawRect(i * blockWidth, 0, (i + 1) * blockWidth, TEST_HEIGHT, paint);
    256             }
    257             return bitmap;
    258         }
    259     };
    260 
    261     private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
    262         private final Rect mBounds = new Rect(30, 30, 150, 150);
    263         private final int[] mColors = new int[] {
    264                 Color.RED, Color.GREEN, Color.BLUE
    265         };
    266 
    267         private final Bitmap mBitmap = createGradient();
    268 
    269         @Override
    270         public void modifyDrawing(Paint paint, Canvas canvas) {
    271             canvas.drawBitmap(mBitmap, 0, 0, paint);
    272         }
    273 
    274         private Bitmap createGradient() {
    275             LinearGradient gradient = new LinearGradient(15, 45, 75, 45, mColors, null,
    276                     Shader.TileMode.REPEAT);
    277             Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
    278             Paint p = new Paint();
    279             p.setShader(gradient);
    280             Canvas c = new Canvas(bitmap);
    281             c.drawRect(mBounds, p);
    282             return bitmap;
    283         }
    284     };
    285 
    286     public static final DisplayModifier mCircleDrawModifier = new DisplayModifier() {
    287         @Override
    288         public void modifyDrawing(Paint paint, Canvas canvas) {
    289             canvas.drawCircle(TEST_WIDTH / 2, TEST_HEIGHT / 2, TEST_HEIGHT / 2, paint);
    290         }
    291     };
    292 
    293     /**
    294      * 0.5 defines minimum similarity as 50%
    295      */
    296     private static final float HIGH_THRESHOLD = 0.5f;
    297 
    298     private static final BitmapComparer[] DEFAULT_MSSIM_COMPARER = new BitmapComparer[] {
    299             new MSSIMComparer(HIGH_THRESHOLD)
    300     };
    301 
    302     @SmallTest
    303     public void testBasicDraws() {
    304         sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, DEFAULT_MSSIM_COMPARER,
    305                 null);
    306     }
    307 
    308     @SmallTest
    309     public void testBasicShaders() {
    310         sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier,
    311                 DEFAULT_MSSIM_COMPARER, null);
    312     }
    313 
    314     @SmallTest
    315     public void testColorFilterUsingGradient() {
    316         sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
    317                 COLOR_FILTER_GRADIENT_MODIFIER, DEFAULT_MSSIM_COMPARER, null);
    318     }
    319 
    320     @SmallTest
    321     public void testColorFiltersAlphas() {
    322         BitmapVerifier[] bitmapVerifiers =
    323                 new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
    324         int index = 0;
    325         for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
    326             bitmapVerifiers[index] = new SamplePointVerifier(COLOR_FILTER_ALPHA_POINTS,
    327                     COLOR_FILTER_ALPHA_MAP.get(mode));
    328             index++;
    329         }
    330         sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
    331                 COLOR_FILTER_ALPHA_MODIFIER, null, bitmapVerifiers);
    332     }
    333 
    334     @SmallTest
    335     public void testXfermodes() {
    336         BitmapVerifier[] bitmapVerifiers =
    337                 new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
    338         int index = 0;
    339         for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
    340             bitmapVerifiers[index] = new SamplePointVerifier(XFERMODE_TEST_POINTS,
    341                     XFERMODE_COLOR_MAP.get(mode));
    342             index++;
    343         }
    344         sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER,
    345                 null, bitmapVerifiers);
    346     }
    347 
    348     /*
    349     @SmallTest
    350     public void testShaderSweeps() {
    351         int mask = DisplayModifier.Accessor.AA_MASK
    352                 | DisplayModifier.Accessor.SHADER_MASK
    353                 | DisplayModifier.Accessor.XFERMODE_MASK
    354                 | DisplayModifier.Accessor.SHAPES_MASK;
    355         sweepModifiersForMask(mask, null, DEFAULT_MSSIM_COMPARER, null);
    356     }
    357     */
    358 
    359     protected void sweepModifiersForMask(int mask, final DisplayModifier drawOp,
    360             BitmapComparer[] bitmapComparers, BitmapVerifier[] bitmapVerifiers) {
    361         if ((mask & DisplayModifier.Accessor.ALL_OPTIONS_MASK) == 0) {
    362             throw new IllegalArgumentException("Attempt to test with a mask that is invalid");
    363         }
    364         // Get the accessor of all the different modifications possible
    365         final DisplayModifier.Accessor modifierAccessor = new DisplayModifier.Accessor(mask);
    366         // Initialize the resources that we will need to access
    367         ResourceModifier.init(getActivity().getResources());
    368         // For each modification combination, we will get the CanvasClient associated with it and
    369         // from there execute a normal canvas test with that.
    370         CanvasClient canvasClient = new CanvasClient() {
    371             @Override
    372             public void draw(Canvas canvas, int width, int height) {
    373                 Paint paint = new Paint();
    374                 modifierAccessor.modifyDrawing(canvas, paint);
    375                 if (drawOp != null) {
    376                     drawOp.modifyDrawing(paint, canvas);
    377                 }
    378             }
    379         };
    380 
    381         int index = 0;
    382         // Create the test cases with each combination
    383         do {
    384             canvasClient.setDebugString(modifierAccessor.getDebugString());
    385             if (bitmapComparers != null) {
    386                 int arrIndex = Math.min(index, bitmapComparers.length - 1);
    387                 createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
    388             } else {
    389                 int arrIndex = Math.min(index, bitmapVerifiers.length - 1);
    390                 createTest().addCanvasClient(canvasClient).runWithVerifier(bitmapVerifiers[arrIndex]);
    391             }
    392             index++;
    393         } while (modifierAccessor.step());
    394     }
    395 }
    396