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