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 com.android.cts.stub.R; 20 21 import dalvik.annotation.KnownFailure; 22 23 import org.xmlpull.v1.XmlPullParser; 24 import org.xmlpull.v1.XmlPullParserException; 25 26 import android.content.res.Resources; 27 import android.content.res.XmlResourceParser; 28 import android.graphics.Bitmap; 29 import android.graphics.BitmapFactory; 30 import android.graphics.Canvas; 31 import android.graphics.Color; 32 import android.graphics.ColorFilter; 33 import android.graphics.NinePatch; 34 import android.graphics.Paint; 35 import android.graphics.PixelFormat; 36 import android.graphics.Rect; 37 import android.graphics.Region; 38 import android.graphics.Bitmap.Config; 39 import android.graphics.drawable.NinePatchDrawable; 40 import android.graphics.drawable.Drawable.ConstantState; 41 import android.test.InstrumentationTestCase; 42 import android.util.AttributeSet; 43 import android.util.Xml; 44 45 import java.io.IOException; 46 47 public class NinePatchDrawableTest extends InstrumentationTestCase { 48 private static final int MIN_CHUNK_SIZE = 32; 49 50 private NinePatchDrawable mNinePatchDrawable; 51 52 private Resources mResources; 53 54 @Override 55 protected void setUp() throws Exception { 56 super.setUp(); 57 mResources = getInstrumentation().getTargetContext().getResources(); 58 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_0); 59 } 60 61 @SuppressWarnings("deprecation") 62 public void testConstructors() { 63 byte[] chunk = new byte[MIN_CHUNK_SIZE]; 64 chunk[MIN_CHUNK_SIZE - 1] = 1; 65 66 Rect r = new Rect(); 67 68 Bitmap bmp = BitmapFactory.decodeResource(mResources, R.drawable.ninepatch_0); 69 String name = mResources.getResourceName(R.drawable.ninepatch_0); 70 71 new NinePatchDrawable(bmp, chunk, r, name); 72 73 new NinePatchDrawable(new NinePatch(bmp, chunk, name)); 74 75 chunk = new byte[MIN_CHUNK_SIZE - 1]; 76 chunk[MIN_CHUNK_SIZE - 2] = 1; 77 try { 78 new NinePatchDrawable(bmp, chunk, r, name); 79 fail("The constructor should check whether the chunk is illegal."); 80 } catch (RuntimeException e) { 81 // This exception is thrown by native method. 82 } 83 } 84 85 public void testDraw() { 86 Bitmap bmp = Bitmap.createBitmap(9, 9, Config.ARGB_8888); 87 Canvas c = new Canvas(bmp); 88 89 int ocean = Color.rgb(0, 0xFF, 0x80); 90 91 mNinePatchDrawable.setBounds(0, 0, 9, 9); 92 mNinePatchDrawable.draw(c); 93 assertColorFillRect(bmp, 0, 0, 4, 4, Color.RED); 94 assertColorFillRect(bmp, 5, 0, 4, 4, Color.BLUE); 95 assertColorFillRect(bmp, 0, 5, 4, 4, ocean); 96 assertColorFillRect(bmp, 5, 5, 4, 4, Color.YELLOW); 97 assertColorFillRect(bmp, 4, 0, 1, 9, Color.WHITE); 98 assertColorFillRect(bmp, 0, 4, 9, 1, Color.WHITE); 99 100 bmp.eraseColor(0xff000000); 101 102 mNinePatchDrawable.setBounds(0, 0, 3, 3); 103 mNinePatchDrawable.draw(c); 104 assertColorFillRect(bmp, 0, 0, 1, 1, Color.RED); 105 assertColorFillRect(bmp, 2, 0, 1, 1, Color.BLUE); 106 assertColorFillRect(bmp, 0, 2, 1, 1, ocean); 107 assertColorFillRect(bmp, 2, 2, 1, 1, Color.YELLOW); 108 assertColorFillRect(bmp, 1, 0, 1, 3, Color.WHITE); 109 assertColorFillRect(bmp, 0, 1, 3, 1, Color.WHITE); 110 111 try { 112 mNinePatchDrawable.draw(null); 113 fail("The method should check whether the canvas is null."); 114 } catch (NullPointerException e) { 115 // expected 116 } 117 } 118 119 public void testGetChangingConfigurations() { 120 ConstantState constantState = mNinePatchDrawable.getConstantState(); 121 122 // default 123 assertEquals(0, constantState.getChangingConfigurations()); 124 assertEquals(0, mNinePatchDrawable.getChangingConfigurations()); 125 126 // change the drawable's configuration does not affect the state's configuration 127 mNinePatchDrawable.setChangingConfigurations(0xff); 128 assertEquals(0xff, mNinePatchDrawable.getChangingConfigurations()); 129 assertEquals(0, constantState.getChangingConfigurations()); 130 131 // the state's configuration get refreshed 132 constantState = mNinePatchDrawable.getConstantState(); 133 assertEquals(0xff, constantState.getChangingConfigurations()); 134 135 // set a new configuration to drawable 136 mNinePatchDrawable.setChangingConfigurations(0xff00); 137 assertEquals(0xff, constantState.getChangingConfigurations()); 138 assertEquals(0xffff, mNinePatchDrawable.getChangingConfigurations()); 139 } 140 141 public void testGetPadding() { 142 Rect r = new Rect(); 143 NinePatchDrawable npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_0); 144 assertTrue(npd.getPadding(r)); 145 // exact padding unknown due to possible density scaling 146 assertEquals(0, r.left); 147 assertEquals(0, r.top); 148 assertTrue(r.right > 0); 149 assertTrue(r.bottom > 0); 150 151 npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_1); 152 assertTrue(npd.getPadding(r)); 153 assertTrue(r.left > 0); 154 assertTrue(r.top > 0); 155 assertTrue(r.right > 0); 156 assertTrue(r.bottom > 0); 157 } 158 159 public void testSetAlpha() { 160 assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha()); 161 162 mNinePatchDrawable.setAlpha(0); 163 assertEquals(0, mNinePatchDrawable.getPaint().getAlpha()); 164 165 mNinePatchDrawable.setAlpha(-1); 166 assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha()); 167 168 mNinePatchDrawable.setAlpha(0xfffe); 169 assertEquals(0xfe, mNinePatchDrawable.getPaint().getAlpha()); 170 } 171 172 public void testSetColorFilter() { 173 assertNull(mNinePatchDrawable.getPaint().getColorFilter()); 174 175 MockColorFilter cf = new MockColorFilter(); 176 mNinePatchDrawable.setColorFilter(cf); 177 assertSame(cf, mNinePatchDrawable.getPaint().getColorFilter()); 178 179 mNinePatchDrawable.setColorFilter(null); 180 assertNull(mNinePatchDrawable.getPaint().getColorFilter()); 181 } 182 183 public void testSetDither() { 184 mNinePatchDrawable.setDither(false); 185 assertFalse(mNinePatchDrawable.getPaint().isDither()); 186 187 mNinePatchDrawable.setDither(true); 188 assertTrue(mNinePatchDrawable.getPaint().isDither()); 189 } 190 191 public void testGetPaint() { 192 Paint paint = mNinePatchDrawable.getPaint(); 193 assertNotNull(paint); 194 195 assertSame(paint, mNinePatchDrawable.getPaint()); 196 } 197 198 public void testGetIntrinsicWidth() { 199 Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0); 200 assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth()); 201 assertEquals(5, mNinePatchDrawable.getIntrinsicWidth()); 202 203 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 204 bmp = getBitmapUnscaled(R.drawable.ninepatch_1); 205 assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth()); 206 assertEquals(9, mNinePatchDrawable.getIntrinsicWidth()); 207 } 208 209 public void testGetMinimumWidth() { 210 Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0); 211 assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth()); 212 assertEquals(5, mNinePatchDrawable.getMinimumWidth()); 213 214 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 215 bmp = getBitmapUnscaled(R.drawable.ninepatch_1); 216 assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth()); 217 assertEquals(9, mNinePatchDrawable.getMinimumWidth()); 218 } 219 220 public void testGetIntrinsicHeight() { 221 Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0); 222 assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight()); 223 assertEquals(5, mNinePatchDrawable.getIntrinsicHeight()); 224 225 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 226 bmp = getBitmapUnscaled(R.drawable.ninepatch_1); 227 assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight()); 228 assertEquals(9, mNinePatchDrawable.getIntrinsicHeight()); 229 } 230 231 public void testGetMinimumHeight() { 232 Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0); 233 assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight()); 234 assertEquals(5, mNinePatchDrawable.getMinimumHeight()); 235 236 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 237 bmp = getBitmapUnscaled(R.drawable.ninepatch_1); 238 assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight()); 239 assertEquals(9, mNinePatchDrawable.getMinimumHeight()); 240 } 241 242 @KnownFailure("Bug 2834281 - Bitmap#hasAlpha seems to return true for " 243 + "images without alpha.") 244 public void testGetOpacity() { 245 assertEquals(PixelFormat.OPAQUE, mNinePatchDrawable.getOpacity()); 246 247 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 248 assertEquals(PixelFormat.TRANSLUCENT, mNinePatchDrawable.getOpacity()); 249 } 250 251 public void testGetTransparentRegion() { 252 // opaque image 253 Region r = mNinePatchDrawable.getTransparentRegion(); 254 assertNull(r); 255 256 mNinePatchDrawable.setBounds(0, 0, 7, 7); 257 r = mNinePatchDrawable.getTransparentRegion(); 258 assertNull(r); 259 260 // translucent image 261 mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1); 262 r = mNinePatchDrawable.getTransparentRegion(); 263 assertNull(r); 264 265 mNinePatchDrawable.setBounds(1, 1, 7, 7); 266 r = mNinePatchDrawable.getTransparentRegion(); 267 assertNotNull(r); 268 assertEquals(new Rect(1, 1, 7, 7), r.getBounds()); 269 } 270 271 public void testGetConstantState() { 272 assertNotNull(mNinePatchDrawable.getConstantState()); 273 274 ConstantState constantState = mNinePatchDrawable.getConstantState(); 275 // change the drawable's configuration does not affect the state's configuration 276 mNinePatchDrawable.setChangingConfigurations(0xff); 277 assertEquals(0, constantState.getChangingConfigurations()); 278 // the state's configuration refreshed when getConstantState is called. 279 constantState = mNinePatchDrawable.getConstantState(); 280 assertEquals(0xff, constantState.getChangingConfigurations()); 281 } 282 283 public void testInflate() throws XmlPullParserException, IOException { 284 final int width = 80; 285 final int height = 120; 286 final int[] COLOR = new int[width * height]; 287 Bitmap bitmap = Bitmap.createBitmap(COLOR, width, height, Bitmap.Config.RGB_565); 288 NinePatchDrawable ninePatchDrawable = 289 new NinePatchDrawable(mResources, bitmap, new byte[1000], null, "TESTNAME"); 290 291 assertEquals(height, ninePatchDrawable.getIntrinsicHeight()); 292 assertEquals(width, ninePatchDrawable.getIntrinsicWidth()); 293 XmlResourceParser parser = mResources.getXml(R.drawable.ninepatchdrawable); 294 int type; 295 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 296 && type != XmlPullParser.START_TAG) { 297 } 298 AttributeSet attrs = Xml.asAttributeSet(parser); 299 ninePatchDrawable.inflate(mResources, parser, attrs); 300 301 assertTrue(ninePatchDrawable.getPaint().isDither()); 302 assertTrue(height != ninePatchDrawable.getIntrinsicHeight()); 303 assertTrue(width != ninePatchDrawable.getIntrinsicWidth()); 304 } 305 306 public void testMutate() { 307 NinePatchDrawable d1 = 308 (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable); 309 NinePatchDrawable d2 = 310 (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable); 311 NinePatchDrawable d3 = 312 (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable); 313 314 // the state is not shared before mutate. 315 d1.setDither(false); 316 assertFalse(d1.getPaint().isDither()); 317 assertTrue(d2.getPaint().isDither()); 318 assertTrue(d3.getPaint().isDither()); 319 320 // cannot test if mutate worked, since state was not shared before 321 d1.mutate(); 322 } 323 324 private void assertColorFillRect(Bitmap bmp, int x, int y, int w, int h, int color) { 325 for (int i = x; i < x + w; i++) { 326 for (int j = y; j < y + h; j++) { 327 assertEquals(color, bmp.getPixel(i, j)); 328 } 329 } 330 } 331 332 private NinePatchDrawable getNinePatchDrawable(int resId) { 333 // jump through hoops to avoid scaling the tiny ninepatch, which would skew the results 334 // depending on device density 335 Bitmap bitmap = getBitmapUnscaled(resId); 336 NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null); 337 return new NinePatchDrawable(mResources, np); 338 } 339 340 private Bitmap getBitmapUnscaled(int resId) { 341 BitmapFactory.Options opts = new BitmapFactory.Options(); 342 opts.inDensity = opts.inTargetDensity = mResources.getDisplayMetrics().densityDpi; 343 Bitmap bitmap = BitmapFactory.decodeResource(mResources, resId, opts); 344 return bitmap; 345 } 346 347 private class MockColorFilter extends ColorFilter { 348 } 349 } 350