1/* 2 * Copyright (C) 2015 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 17package android.uirendering.cts.testclasses; 18 19import android.graphics.Bitmap; 20import android.graphics.BitmapShader; 21import android.graphics.Canvas; 22import android.graphics.Color; 23import android.graphics.ComposeShader; 24import android.graphics.LinearGradient; 25import android.graphics.Paint; 26import android.graphics.PorterDuff; 27import android.graphics.RadialGradient; 28import android.graphics.Shader; 29import android.support.test.filters.MediumTest; 30import android.support.test.runner.AndroidJUnit4; 31import android.uirendering.cts.bitmapcomparers.MSSIMComparer; 32import android.uirendering.cts.bitmapverifiers.ColorVerifier; 33import android.uirendering.cts.testinfrastructure.ActivityTestBase; 34import android.uirendering.cts.testinfrastructure.CanvasClient; 35 36import org.junit.Test; 37import org.junit.runner.RunWith; 38 39@MediumTest 40@RunWith(AndroidJUnit4.class) 41public class ShaderTests extends ActivityTestBase { 42 @Test 43 public void testSinglePixelBitmapShader() { 44 createTest() 45 .addCanvasClient(new CanvasClient() { 46 Paint mPaint = new Paint(); 47 @Override 48 public void draw(Canvas canvas, int width, int height) { 49 if (mPaint.getShader() == null) { 50 Bitmap shaderBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 51 shaderBitmap.eraseColor(Color.BLUE); 52 mPaint.setShader(new BitmapShader(shaderBitmap, 53 Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)); 54 } 55 canvas.drawRect(0, 0, width, height, mPaint); 56 } 57 }) 58 .runWithVerifier(new ColorVerifier(Color.BLUE)); 59 } 60 61 @Test 62 public void testSinglePixelComposeShader() { 63 createTest() 64 .addCanvasClient(new CanvasClient() { 65 Paint mPaint = new Paint(); 66 67 @Override 68 public void draw(Canvas canvas, int width, int height) { 69 if (mPaint.getShader() == null) { 70 // BLUE as SRC for Compose 71 Bitmap shaderBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 72 shaderBitmap.eraseColor(Color.BLUE); 73 BitmapShader bitmapShader = new BitmapShader(shaderBitmap, 74 Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 75 76 // Fully opaque gradient mask (via DST_IN). 77 // In color array, only alpha channel will matter. 78 RadialGradient gradientShader = new RadialGradient( 79 10, 10, 10, 80 new int[] { Color.RED, Color.GREEN, Color.BLUE }, null, 81 Shader.TileMode.CLAMP); 82 83 mPaint.setShader(new ComposeShader( 84 bitmapShader, gradientShader, PorterDuff.Mode.DST_IN)); 85 } 86 canvas.drawRect(0, 0, width, height, mPaint); 87 } 88 }) 89 .runWithVerifier(new ColorVerifier(Color.BLUE)); 90 } 91 92 @Test 93 public void testComplexShaderUsage() { 94 /* 95 * This test not only builds a very complex drawing operation, but also tests an 96 * implementation detail of HWUI, using the largest number of texture sample sources 97 * possible - 4. 98 * 99 * 1) Bitmap passed to canvas.drawBitmap 100 * 2) gradient color lookup 101 * 3) gradient dither lookup 102 * 4) Bitmap in BitmapShader 103 */ 104 createTest() 105 .addCanvasClient(new CanvasClient() { 106 Paint mPaint = new Paint(); 107 Bitmap mBitmap; 108 109 @Override 110 public void draw(Canvas canvas, int width, int height) { 111 if (mBitmap == null) { 112 mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8); 113 // Primary content mask 114 Canvas bitmapCanvas = new Canvas(mBitmap); 115 final float radius = width / 2.0f; 116 bitmapCanvas.drawCircle(width / 2, height / 2, radius, mPaint); 117 118 // Bitmap shader mask, partially overlapping content 119 Bitmap shaderBitmap = Bitmap.createBitmap( 120 width, height, Bitmap.Config.ALPHA_8); 121 bitmapCanvas = new Canvas(shaderBitmap); 122 bitmapCanvas.drawCircle(width / 2, 0, radius, mPaint); 123 bitmapCanvas.drawCircle(width / 2, height, radius, mPaint); 124 BitmapShader bitmapShader = new BitmapShader(shaderBitmap, 125 Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 126 127 // Gradient fill 128 RadialGradient gradientShader = new RadialGradient( 129 width / 2, height / 2, radius, 130 new int[] { Color.RED, Color.BLUE, Color.GREEN }, 131 null, Shader.TileMode.CLAMP); 132 133 mPaint.setShader(new ComposeShader(gradientShader, bitmapShader, 134 PorterDuff.Mode.DST_IN)); 135 } 136 canvas.drawBitmap(mBitmap, 0, 0, mPaint); 137 } 138 }) 139 // expect extremely similar rendering results between SW and HW, since there's no AA 140 .runWithComparer(new MSSIMComparer(0.98f)); 141 } 142 143 @Test 144 public void testRepeatAlphaGradientShader() { 145 createTest() 146 .addCanvasClient(new CanvasClient() { 147 Paint mPaint = new Paint(); 148 @Override 149 public void draw(Canvas canvas, int width, int height) { 150 if (mPaint.getShader() == null) { 151 mPaint.setShader(new LinearGradient(0, 0, width / 2.0f, height, 152 Color.TRANSPARENT, Color.WHITE, Shader.TileMode.REPEAT)); 153 } 154 canvas.drawColor(Color.WHITE); 155 canvas.drawRect(0, 0, width, height, mPaint); 156 } 157 }) 158 .runWithVerifier(new ColorVerifier(Color.WHITE)); 159 } 160 161 @Test 162 public void testClampAlphaGradientShader() { 163 createTest() 164 .addCanvasClient(new CanvasClient() { 165 Paint mPaint = new Paint(); 166 @Override 167 public void draw(Canvas canvas, int width, int height) { 168 if (mPaint.getShader() == null) { 169 mPaint.setShader(new LinearGradient(0, 0, width / 2.0f, height, 170 Color.TRANSPARENT, Color.WHITE, Shader.TileMode.CLAMP)); 171 } 172 canvas.drawColor(Color.WHITE); 173 canvas.drawRect(0, 0, width, height, mPaint); 174 } 175 }) 176 .runWithVerifier(new ColorVerifier(Color.WHITE)); 177 } 178} 179