1 /*
2  * Copyright (C) 2016 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 package android.uirendering.cts.testclasses;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNotSame;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertSame;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26 
27 import android.content.res.Resources.Theme;
28 import android.graphics.BitmapFactory;
29 import android.graphics.Rect;
30 
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import android.content.Context;
35 import android.content.res.Configuration;
36 import android.content.res.Resources;
37 import android.content.res.XmlResourceParser;
38 import android.graphics.Bitmap;
39 import android.graphics.Canvas;
40 import android.graphics.Color;
41 import android.graphics.drawable.BitmapDrawable;
42 import android.graphics.drawable.Drawable;
43 import android.graphics.drawable.Drawable.ConstantState;
44 import android.support.test.InstrumentationRegistry;
45 import android.support.test.filters.MediumTest;
46 import android.support.test.runner.AndroidJUnit4;
47 import android.uirendering.cts.R;
48 import android.uirendering.cts.bitmapverifiers.RectVerifier;
49 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
50 import android.uirendering.cts.testinfrastructure.CanvasClient;
51 import android.util.LayoutDirection;
52 
53 import java.io.ByteArrayInputStream;
54 import java.io.File;
55 import java.io.FileOutputStream;
56 import java.io.IOException;
57 import java.io.InputStream;
58 
59 @MediumTest
60 @RunWith(AndroidJUnit4.class)
61 public class BitmapDrawableTest extends ActivityTestBase {
62 
63     // The target context.
64     private Context mContext;
65 
66     @Before
setup()67     public void setup() {
68         mContext = InstrumentationRegistry.getTargetContext();
69     }
70 
71     private static final int[] DENSITY_VALUES = new int[] {
72             160, 80, 320
73     };
74 
75     private static final int[] DENSITY_IMAGES = new int[] {
76             R.drawable.bitmap_density,
77             R.drawable.bitmap_shader_density,
78             R.drawable.bitmap_shader_am_density,
79     };
80 
81     @Test
testPreloadDensity()82     public void testPreloadDensity() throws IOException {
83         final Resources res = mContext.getResources();
84         final int densityDpi = res.getConfiguration().densityDpi;
85         try {
86             for (int i = 0; i < DENSITY_IMAGES.length; i++) {
87                 verifyPreloadDensityInner(res, DENSITY_IMAGES[i], DENSITY_VALUES);
88             }
89         } finally {
90             setResourcesDensity(res, densityDpi);
91         }
92     }
93 
verifyPreloadDensityInner(Resources res, int sourceResId, int[] densities)94     private void verifyPreloadDensityInner(Resources res, int sourceResId, int[] densities)
95             throws IOException {
96         final Rect tempPadding = new Rect();
97 
98         // Capture initial state at preload density.
99         final int preloadDensityDpi = densities[0];
100         setResourcesDensity(res, preloadDensityDpi);
101 
102         final BitmapDrawable preloadedDrawable = (BitmapDrawable) res.getDrawable(sourceResId);
103         final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
104         final int origWidth = preloadedDrawable.getIntrinsicWidth();
105         final int origHeight = preloadedDrawable.getIntrinsicHeight();
106         assertFalse(preloadedDrawable.getPadding(tempPadding));
107 
108         runTest(preloadedDrawable);
109 
110         for (int i = 1; i < densities.length; i++) {
111             final int scaledDensityDpi = densities[i];
112             final float scale = scaledDensityDpi / (float) preloadDensityDpi;
113             setResourcesDensity(res, scaledDensityDpi);
114 
115             final BitmapDrawable scaledDrawable =
116                     (BitmapDrawable) preloadedConstantState.newDrawable(res);
117             scaledDrawable.setLayoutDirection(LayoutDirection.RTL);
118 
119             // Sizes are rounded.
120             assertEquals(Math.round(origWidth * scale), scaledDrawable.getIntrinsicWidth());
121             assertEquals(Math.round(origHeight * scale), scaledDrawable.getIntrinsicHeight());
122 
123             // Bitmaps have no padding.
124             assertFalse(scaledDrawable.getPadding(tempPadding));
125 
126             runTest(scaledDrawable);
127 
128             // Ensure theme density is applied correctly. Unlike most
129             // drawables, we don't have any loss of accuracy because density
130             // changes are re-computed from the source every time.
131             setResourcesDensity(res, preloadDensityDpi);
132 
133             final Theme t = res.newTheme();
134             scaledDrawable.applyTheme(t);
135             assertEquals(origWidth, scaledDrawable.getIntrinsicWidth());
136             assertEquals(origHeight, scaledDrawable.getIntrinsicHeight());
137             assertFalse(scaledDrawable.getPadding(tempPadding));
138         }
139     }
140 
runTest(Drawable dr)141     private void runTest(Drawable dr) {
142         final Rect drBounds = new Rect(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
143         CanvasClient canvasClient = (canvas, width, height) -> {
144             assertTrue(width > drBounds.width());
145             assertTrue(height > drBounds.height());
146             dr.setBounds(drBounds);
147             dr.draw(canvas);
148         };
149         createTest()
150                 .addCanvasClient(canvasClient)
151                 .runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, drBounds));
152     }
153 
setResourcesDensity(Resources res, int densityDpi)154     private static void setResourcesDensity(Resources res, int densityDpi) {
155         final Configuration config = new Configuration();
156         config.setTo(res.getConfiguration());
157         config.densityDpi = densityDpi;
158         res.updateConfiguration(config, null);
159     }
160 }
161