1 /* 2 * Copyright (C) 2008 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 17 package android.graphics.drawable.cts; 18 19 import android.graphics.Canvas; 20 import android.graphics.drawable.Drawable; 21 import junit.framework.Assert; 22 23 import org.xmlpull.v1.XmlPullParser; 24 import org.xmlpull.v1.XmlPullParserException; 25 26 import android.content.res.Configuration; 27 import android.content.res.Resources; 28 import android.content.res.XmlResourceParser; 29 import android.graphics.Bitmap; 30 import android.graphics.Color; 31 import android.util.AttributeSet; 32 import android.util.Xml; 33 34 import java.io.IOException; 35 36 /** 37 * The useful methods for graphics.drawable test. 38 */ 39 public class DrawableTestUtils { 40 skipCurrentTag(XmlPullParser parser)41 public static void skipCurrentTag(XmlPullParser parser) 42 throws XmlPullParserException, IOException { 43 int outerDepth = parser.getDepth(); 44 int type; 45 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 46 && (type != XmlPullParser.END_TAG 47 || parser.getDepth() > outerDepth)) { 48 } 49 } 50 51 /** 52 * Retrieve an AttributeSet from a XML. 53 * 54 * @param parser the XmlPullParser to use for the xml parsing. 55 * @param searchedNodeName the name of the target node. 56 * @return the AttributeSet retrieved from specified node. 57 * @throws IOException 58 * @throws XmlPullParserException 59 */ getAttributeSet(XmlResourceParser parser, String searchedNodeName)60 public static AttributeSet getAttributeSet(XmlResourceParser parser, String searchedNodeName) 61 throws XmlPullParserException, IOException { 62 AttributeSet attrs = null; 63 int type; 64 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 65 && type != XmlPullParser.START_TAG) { 66 } 67 String nodeName = parser.getName(); 68 if (!"alias".equals(nodeName)) { 69 throw new RuntimeException(); 70 } 71 int outerDepth = parser.getDepth(); 72 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 73 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 74 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 75 continue; 76 } 77 nodeName = parser.getName(); 78 if (searchedNodeName.equals(nodeName)) { 79 outerDepth = parser.getDepth(); 80 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 81 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 82 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 83 continue; 84 } 85 nodeName = parser.getName(); 86 attrs = Xml.asAttributeSet(parser); 87 break; 88 } 89 break; 90 } else { 91 skipCurrentTag(parser); 92 } 93 } 94 return attrs; 95 } 96 getResourceParser(Resources res, int resId)97 public static XmlResourceParser getResourceParser(Resources res, int resId) 98 throws XmlPullParserException, IOException { 99 final XmlResourceParser parser = res.getXml(resId); 100 int type; 101 while ((type = parser.next()) != XmlPullParser.START_TAG 102 && type != XmlPullParser.END_DOCUMENT) { 103 // Empty loop 104 } 105 return parser; 106 } 107 setResourcesDensity(Resources res, int densityDpi)108 public static void setResourcesDensity(Resources res, int densityDpi) { 109 final Configuration config = new Configuration(); 110 config.setTo(res.getConfiguration()); 111 config.densityDpi = densityDpi; 112 res.updateConfiguration(config, null); 113 } 114 115 /** 116 * Implements scaling as used by the Bitmap class. Resulting values are 117 * rounded up (as distinct from resource scaling, which truncates or rounds 118 * to the nearest pixel). 119 * 120 * @param size the pixel size to scale 121 * @param sdensity the source density that corresponds to the size 122 * @param tdensity the target density 123 * @return the pixel size scaled for the target density 124 */ scaleBitmapFromDensity(int size, int sdensity, int tdensity)125 public static int scaleBitmapFromDensity(int size, int sdensity, int tdensity) { 126 if (sdensity == 0 || tdensity == 0 || sdensity == tdensity) { 127 return size; 128 } 129 130 // Scale by tdensity / sdensity, rounding up. 131 return ((size * tdensity) + (sdensity >> 1)) / sdensity; 132 } 133 134 /** 135 * Asserts that two images are similar within the given thresholds. 136 * 137 * @param message Error message 138 * @param expected Expected bitmap 139 * @param actual Actual bitmap 140 * @param pixelThreshold The total difference threshold for a single pixel 141 * @param pixelCountThreshold The total different pixel count threshold 142 * @param pixelDiffTolerance The pixel value difference tolerance 143 * 144 */ compareImages(String message, Bitmap expected, Bitmap actual, float pixelThreshold, float pixelCountThreshold, int pixelDiffTolerance)145 public static void compareImages(String message, Bitmap expected, Bitmap actual, 146 float pixelThreshold, float pixelCountThreshold, int pixelDiffTolerance) { 147 int idealWidth = expected.getWidth(); 148 int idealHeight = expected.getHeight(); 149 150 Assert.assertTrue(idealWidth == actual.getWidth()); 151 Assert.assertTrue(idealHeight == actual.getHeight()); 152 153 int totalDiffPixelCount = 0; 154 float totalPixelCount = idealWidth * idealHeight; 155 for (int x = 0; x < idealWidth; x++) { 156 for (int y = 0; y < idealHeight; y++) { 157 int idealColor = expected.getPixel(x, y); 158 int givenColor = actual.getPixel(x, y); 159 if (idealColor == givenColor) 160 continue; 161 162 float totalError = 0; 163 totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor)); 164 totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor)); 165 totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor)); 166 totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor)); 167 168 if ((totalError / 1024.0f) >= pixelThreshold) { 169 Assert.fail((message + ": totalError is " + totalError)); 170 } 171 172 if (totalError > pixelDiffTolerance) { 173 totalDiffPixelCount++; 174 } 175 } 176 } 177 if ((totalDiffPixelCount / totalPixelCount) >= pixelCountThreshold) { 178 Assert.fail((message +": totalDiffPixelCount is " + totalDiffPixelCount)); 179 } 180 } 181 182 /** 183 * Returns the {@link Color} at the specified location in the {@link Drawable}. 184 */ getPixel(Drawable d, int x, int y)185 public static int getPixel(Drawable d, int x, int y) { 186 final int w = Math.max(d.getIntrinsicWidth(), x + 1); 187 final int h = Math.max(d.getIntrinsicHeight(), y + 1); 188 final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 189 final Canvas c = new Canvas(b); 190 d.setBounds(0, 0, w, h); 191 d.draw(c); 192 193 final int pixel = b.getPixel(x, y); 194 b.recycle(); 195 return pixel; 196 } 197 } 198