1 /* 2 * Copyright (C) 2016 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/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, 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.app.Activity; 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Color; 22 import android.graphics.Paint; 23 import android.graphics.Point; 24 import android.graphics.PorterDuff; 25 import android.graphics.PorterDuffXfermode; 26 import android.graphics.RectF; 27 import android.graphics.drawable.ColorDrawable; 28 import android.support.test.filters.LargeTest; 29 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier; 30 import android.uirendering.cts.testinfrastructure.ActivityTestBase; 31 import android.uirendering.cts.testinfrastructure.CanvasClient; 32 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.junit.runners.Parameterized; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 @LargeTest // Temporarily hidden from presubmit 42 @RunWith(Parameterized.class) 43 public class XfermodeTest extends ActivityTestBase { 44 /** 45 * There are 4 locations we care about in testing each filter: 46 * 47 * 1) Both empty 48 * 2) Only src, dst empty 49 * 3) Both src + dst 50 * 4) Only dst, src empty 51 */ 52 private final static Point[] TEST_POINTS = new Point[] { 53 new Point(1, 80), 54 new Point(25, 25), 55 new Point(35, 35), 56 new Point(70, 70) 57 }; 58 59 public static class Config { 60 final boolean hardwareAccelerated; 61 final PorterDuff.Mode mode; 62 final int[] expectedColors; 63 64 Config(boolean hardwareAccelerated, Object[] modeAndExpectedColors) { 65 this.hardwareAccelerated = hardwareAccelerated; 66 mode = (PorterDuff.Mode) modeAndExpectedColors[0]; 67 expectedColors = (int[]) modeAndExpectedColors[1]; 68 } 69 70 @Override 71 public String toString() { 72 return mode.name() + ", hardwareAccelerated=" + hardwareAccelerated; 73 } 74 }; 75 76 public static List<XfermodeTest.Config> configs(Object[][] modesAndExpectedColors) { 77 List<XfermodeTest.Config> configs = new ArrayList<>(); 78 for (boolean hardwareAccelerated : new boolean[] {false, true}) { 79 for (Object[] modeAndExpectedColors : modesAndExpectedColors) { 80 configs.add(new XfermodeTest.Config(hardwareAccelerated, modeAndExpectedColors)); 81 } 82 } 83 return configs; 84 } 85 86 private static final int BG_COLOR = 0xFFFFFFFF; 87 private static final int DST_COLOR = 0xFFFFCC44; 88 private static final int SRC_COLOR = 0xFF66AAFF; 89 private static final int MULTIPLY_COLOR = 0xFF668844; 90 private static final int SCREEN_COLOR = 0xFFFFEEFF; 91 92 private static Object[][] MODES_AND_EXPECTED_COLORS = new Object[][] { 93 { PorterDuff.Mode.SRC, new int[] { 94 BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR } }, 95 96 { PorterDuff.Mode.DST, new int[] { 97 BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR } }, 98 99 { PorterDuff.Mode.SRC_OVER, new int[] { 100 BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR } }, 101 102 { PorterDuff.Mode.DST_OVER, new int[] { 103 BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR } }, 104 105 { PorterDuff.Mode.SRC_IN, new int[] { 106 BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR } }, 107 108 { PorterDuff.Mode.DST_IN, new int[] { 109 BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR } }, 110 111 { PorterDuff.Mode.SRC_OUT, new int[] { 112 BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR } }, 113 114 { PorterDuff.Mode.DST_OUT, new int[] { 115 BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR } }, 116 117 { PorterDuff.Mode.SRC_ATOP, new int[] { 118 BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR } }, 119 120 { PorterDuff.Mode.DST_ATOP, new int[] { 121 BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR } }, 122 123 { PorterDuff.Mode.XOR, new int[] { 124 BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR } }, 125 126 { PorterDuff.Mode.MULTIPLY, new int[] { 127 BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR } }, 128 129 { PorterDuff.Mode.SCREEN, new int[] { 130 BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR } }, 131 132 { PorterDuff.Mode.CLEAR, new int[] { 133 BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR } }, 134 }; 135 136 @Parameterized.Parameters 137 public static List<Config> configs() { 138 return configs(MODES_AND_EXPECTED_COLORS); 139 } 140 141 private final Config mConfig; 142 143 public XfermodeTest(Config config) { 144 mConfig = config; 145 } 146 147 148 @Before 149 public void setUp() { 150 // temporary - ensure test isn't capturing window bg only 151 final Activity activity = getActivity(); 152 getInstrumentation().runOnMainSync(() -> activity.getWindow().setBackgroundDrawable( 153 new ColorDrawable(Color.GREEN))); 154 155 } 156 157 private CanvasClient mCanvasClient = new CanvasClient() { 158 final Paint mPaint = new Paint(); 159 private final RectF mSrcRect = new RectF(30, 30, 80, 80); 160 private final RectF mDstRect = new RectF(10, 10, 60, 60); 161 private final Bitmap mSrcBitmap = createSrc(); 162 private final Bitmap mDstBitmap = createDst(); 163 164 @Override 165 public void draw(Canvas canvas, int width, int height) { 166 canvas.drawColor(Color.WHITE); // temporary - ensure test isn't capturing window bg only 167 168 int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null); 169 170 canvas.drawBitmap(mDstBitmap, 0, 0, null); 171 mPaint.setXfermode(new PorterDuffXfermode(mConfig.mode)); 172 canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint); 173 174 canvas.restoreToCount(sc); 175 } 176 177 private Bitmap createSrc() { 178 Bitmap srcB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888); 179 Canvas srcCanvas = new Canvas(srcB); 180 Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 181 srcPaint.setColor(SRC_COLOR); 182 srcCanvas.drawRect(mSrcRect, srcPaint); 183 return srcB; 184 } 185 186 private Bitmap createDst() { 187 Bitmap dstB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888); 188 Canvas dstCanvas = new Canvas(dstB); 189 Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 190 dstPaint.setColor(DST_COLOR); 191 dstCanvas.drawOval(mDstRect, dstPaint); 192 return dstB; 193 } 194 }; 195 196 @Test 197 public void test() { 198 createTest() 199 .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated) 200 .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors)); 201 } 202 } 203