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