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 17package android.support.design.testutils; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.graphics.Bitmap; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.graphics.Rect; 25import android.graphics.drawable.Drawable; 26import android.support.annotation.ColorInt; 27import android.support.annotation.NonNull; 28 29import junit.framework.Assert; 30 31public class TestUtils { 32 /** 33 * Checks whether all the pixels in the specified drawable are of the same specified color. 34 * 35 * In case there is a color mismatch, the behavior of this method depends on the 36 * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will 37 * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call 38 * <code>Assert.fail</code> with detailed description of the mismatch. 39 */ 40 public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable, 41 int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color, 42 int allowedComponentVariance, boolean throwExceptionIfFails) { 43 assertAllPixelsOfColor(failMessagePrefix, drawable, drawableWidth, drawableHeight, 44 callSetBounds, color, null, allowedComponentVariance, throwExceptionIfFails); 45 } 46 47 public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable, 48 int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color, 49 Rect checkArea, int allowedComponentVariance, boolean throwExceptionIfFails) { 50 51 // Create a bitmap 52 Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight, Bitmap.Config.ARGB_8888); 53 // Create a canvas that wraps the bitmap 54 Canvas canvas = new Canvas(bitmap); 55 if (callSetBounds) { 56 // Configure the drawable to have bounds that match the passed size 57 drawable.setBounds(0, 0, drawableWidth, drawableHeight); 58 } 59 60 // And ask the drawable to draw itself to the canvas / bitmap 61 drawable.draw(canvas); 62 63 try { 64 int[] rowPixels = new int[drawableWidth]; 65 66 final int firstRow = checkArea != null ? checkArea.top : 0; 67 final int lastRow = checkArea != null ? checkArea.bottom : drawableHeight - 1; 68 final int firstCol = checkArea != null ? checkArea.left : 0; 69 final int lastCol = checkArea != null ? checkArea.right : drawableWidth - 1; 70 71 final int expectedAlpha = Color.alpha(color); 72 final int expectedRed = Color.red(color); 73 final int expectedGreen = Color.green(color); 74 final int expectedBlue = Color.blue(color); 75 76 for (int row = firstRow; row <= lastRow; row++) { 77 bitmap.getPixels(rowPixels, 0, drawableWidth, 0, row, drawableWidth, 1); 78 79 for (int column = firstCol; column <= lastCol; column++) { 80 int sourceAlpha = Color.alpha(rowPixels[column]); 81 int sourceRed = Color.red(rowPixels[column]); 82 int sourceGreen = Color.green(rowPixels[column]); 83 int sourceBlue = Color.blue(rowPixels[column]); 84 85 int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha); 86 int varianceRed = Math.abs(sourceRed - expectedRed); 87 int varianceGreen = Math.abs(sourceGreen - expectedGreen); 88 int varianceBlue = Math.abs(sourceBlue - expectedBlue); 89 90 boolean isColorMatch = (varianceAlpha <= allowedComponentVariance) 91 && (varianceRed <= allowedComponentVariance) 92 && (varianceGreen <= allowedComponentVariance) 93 && (varianceBlue <= allowedComponentVariance); 94 95 if (!isColorMatch) { 96 String mismatchDescription = failMessagePrefix 97 + ": expected all drawable colors to be [" 98 + expectedAlpha + "," + expectedRed + "," 99 + expectedGreen + "," + expectedBlue 100 + "] but at position (" + row + "," + column + ") found [" 101 + sourceAlpha + "," + sourceRed + "," 102 + sourceGreen + "," + sourceBlue + "]"; 103 if (throwExceptionIfFails) { 104 throw new RuntimeException(mismatchDescription); 105 } else { 106 Assert.fail(mismatchDescription); 107 } 108 } 109 } 110 } 111 } finally { 112 bitmap.recycle(); 113 } 114 } 115 116 public static int getThemeAttrColor(Context context, final int attr) { 117 TypedArray a = null; 118 try { 119 a = context.obtainStyledAttributes(new int[]{attr}); 120 return a.getColor(0, 0); 121 } finally { 122 if (a != null) { 123 a.recycle(); 124 } 125 } 126 } 127}