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