/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics.drawable.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.NinePatch;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.cts.R;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Xml;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class NinePatchDrawableTest {
    // A small value is actually making sure that the values are matching
    // exactly with the golden image.
    // We can increase the threshold if the Skia is drawing with some variance
    // on different devices. So far, the tests show they are matching correctly.
    private static final float PIXEL_ERROR_THRESHOLD = 0.03f;
    private static final float PIXEL_ERROR_COUNT_THRESHOLD = 0.005f;

    private static final int MIN_CHUNK_SIZE = 32;

    // Set true to generate golden images, false for normal tests.
    private static final boolean DBG_DUMP_PNG = false;

    private NinePatchDrawable mNinePatchDrawable;

    private Resources mResources;

    @Before
    public void setup() {
        mResources = InstrumentationRegistry.getTargetContext().getResources();
        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_0);
    }

    @SuppressWarnings("deprecation")
    @Test
    public void testConstructors() {
        byte[] chunk = new byte[MIN_CHUNK_SIZE];
        chunk[MIN_CHUNK_SIZE - 1] = 1;

        Rect r = new Rect();

        Bitmap bmp = BitmapFactory.decodeResource(mResources, R.drawable.ninepatch_0);
        String name = mResources.getResourceName(R.drawable.ninepatch_0);

        new NinePatchDrawable(bmp, chunk, r, name);

        new NinePatchDrawable(new NinePatch(bmp, chunk, name));

        chunk = new byte[MIN_CHUNK_SIZE - 1];
        chunk[MIN_CHUNK_SIZE - 2] = 1;
        try {
            new NinePatchDrawable(bmp, chunk, r, name);
            fail("The constructor should check whether the chunk is illegal.");
        } catch (RuntimeException e) {
            // This exception is thrown by native method.
        }
    }

    @Test
    public void testDraw() {
        Bitmap bmp = Bitmap.createBitmap(9, 9, Config.ARGB_8888);
        Canvas c = new Canvas(bmp);

        int ocean = Color.rgb(0, 0xFF, 0x80);

        mNinePatchDrawable.setBounds(0, 0, 9, 9);
        mNinePatchDrawable.draw(c);
        verifyColorFillRect(bmp, 0, 0, 4, 4, Color.RED);
        verifyColorFillRect(bmp, 5, 0, 4, 4, Color.BLUE);
        verifyColorFillRect(bmp, 0, 5, 4, 4, ocean);
        verifyColorFillRect(bmp, 5, 5, 4, 4, Color.YELLOW);
        verifyColorFillRect(bmp, 4, 0, 1, 9, Color.WHITE);
        verifyColorFillRect(bmp, 0, 4, 9, 1, Color.WHITE);

        bmp.eraseColor(0xff000000);

        mNinePatchDrawable.setBounds(0, 0, 3, 3);
        mNinePatchDrawable.draw(c);
        verifyColorFillRect(bmp, 0, 0, 1, 1, Color.RED);
        verifyColorFillRect(bmp, 2, 0, 1, 1, Color.BLUE);
        verifyColorFillRect(bmp, 0, 2, 1, 1, ocean);
        verifyColorFillRect(bmp, 2, 2, 1, 1, Color.YELLOW);
        verifyColorFillRect(bmp, 1, 0, 1, 3, Color.WHITE);
        verifyColorFillRect(bmp, 0, 1, 3, 1, Color.WHITE);
    }

    @Test(expected=NullPointerException.class)
    public void testDrawNullCanvas() {
        mNinePatchDrawable.draw(null);
    }

    @Test
    public void testGetChangingConfigurations() {
        ConstantState constantState = mNinePatchDrawable.getConstantState();

        // default
        assertEquals(0, constantState.getChangingConfigurations());
        assertEquals(0, mNinePatchDrawable.getChangingConfigurations());

        // change the drawable's configuration does not affect the state's configuration
        mNinePatchDrawable.setChangingConfigurations(0xff);
        assertEquals(0xff, mNinePatchDrawable.getChangingConfigurations());
        assertEquals(0, constantState.getChangingConfigurations());

        // the state's configuration get refreshed
        constantState = mNinePatchDrawable.getConstantState();
        assertEquals(0xff,  constantState.getChangingConfigurations());

        // set a new configuration to drawable
        mNinePatchDrawable.setChangingConfigurations(0xff00);
        assertEquals(0xff,  constantState.getChangingConfigurations());
        assertEquals(0xffff,  mNinePatchDrawable.getChangingConfigurations());
    }

    @Test
    public void testGetPadding() {
        Rect r = new Rect();
        NinePatchDrawable npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_0);
        assertTrue(npd.getPadding(r));
        // exact padding unknown due to possible density scaling
        assertEquals(0, r.left);
        assertEquals(0, r.top);
        assertTrue(r.right > 0);
        assertTrue(r.bottom > 0);

        npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_1);
        assertTrue(npd.getPadding(r));
        assertTrue(r.left > 0);
        assertTrue(r.top > 0);
        assertTrue(r.right > 0);
        assertTrue(r.bottom > 0);
    }

    @Test
    public void testSetAlpha() {
        assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha());

        mNinePatchDrawable.setAlpha(0);
        assertEquals(0, mNinePatchDrawable.getPaint().getAlpha());

        mNinePatchDrawable.setAlpha(-1);
        assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha());

        mNinePatchDrawable.setAlpha(0xfffe);
        assertEquals(0xfe, mNinePatchDrawable.getPaint().getAlpha());
    }

    @Test
    public void testSetColorFilter() {
        assertNull(mNinePatchDrawable.getPaint().getColorFilter());

        ColorFilter cf = new ColorFilter();
        mNinePatchDrawable.setColorFilter(cf);
        assertSame(cf, mNinePatchDrawable.getPaint().getColorFilter());

        mNinePatchDrawable.setColorFilter(null);
        assertNull(mNinePatchDrawable.getPaint().getColorFilter());
    }

    @Test
    public void testSetTint() {
        mNinePatchDrawable.setTint(Color.BLACK);
        mNinePatchDrawable.setTintMode(Mode.SRC_OVER);
        assertEquals("Nine-patch is tinted", Color.BLACK,
                DrawableTestUtils.getPixel(mNinePatchDrawable, 0, 0));

        mNinePatchDrawable.setTintList(null);
        mNinePatchDrawable.setTintMode(null);
    }

    @Test
    public void testSetDither() {
        mNinePatchDrawable.setDither(false);
        assertFalse(mNinePatchDrawable.getPaint().isDither());

        mNinePatchDrawable.setDither(true);
        assertTrue(mNinePatchDrawable.getPaint().isDither());
    }

    @Test
    public void testSetFilterBitmap() {
        mNinePatchDrawable.setFilterBitmap(false);
        assertFalse(mNinePatchDrawable.getPaint().isFilterBitmap());

        mNinePatchDrawable.setFilterBitmap(true);
        assertTrue(mNinePatchDrawable.getPaint().isFilterBitmap());
    }

    @Test
    public void testIsFilterBitmap() {
        mNinePatchDrawable.setFilterBitmap(false);
        assertFalse(mNinePatchDrawable.isFilterBitmap());
        assertEquals(mNinePatchDrawable.isFilterBitmap(),
                mNinePatchDrawable.getPaint().isFilterBitmap());


        mNinePatchDrawable.setFilterBitmap(true);
        assertTrue(mNinePatchDrawable.isFilterBitmap());
        assertEquals(mNinePatchDrawable.isFilterBitmap(),
                mNinePatchDrawable.getPaint().isFilterBitmap());
    }

    @Test
    public void testGetPaint() {
        Paint paint = mNinePatchDrawable.getPaint();
        assertNotNull(paint);

        assertSame(paint, mNinePatchDrawable.getPaint());
    }

    @Test
    public void testGetIntrinsicWidth() {
        Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
        assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth());
        assertEquals(5, mNinePatchDrawable.getIntrinsicWidth());

        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
        assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth());
        assertEquals(9, mNinePatchDrawable.getIntrinsicWidth());
    }

    @Test
    public void testGetMinimumWidth() {
        Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
        assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth());
        assertEquals(5, mNinePatchDrawable.getMinimumWidth());

        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
        assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth());
        assertEquals(9, mNinePatchDrawable.getMinimumWidth());
    }

    @Test
    public void testGetIntrinsicHeight() {
        Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
        assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight());
        assertEquals(5, mNinePatchDrawable.getIntrinsicHeight());

        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
        assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight());
        assertEquals(9, mNinePatchDrawable.getIntrinsicHeight());
    }

    @Test
    public void testGetMinimumHeight() {
        Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
        assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight());
        assertEquals(5, mNinePatchDrawable.getMinimumHeight());

        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
        assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight());
        assertEquals(9, mNinePatchDrawable.getMinimumHeight());
    }

    // Known failure: Bug 2834281 - Bitmap#hasAlpha seems to return true for
    // images without alpha
    @Ignore
    @Test
    public void testGetOpacity() {
        assertEquals(PixelFormat.OPAQUE, mNinePatchDrawable.getOpacity());

        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        assertEquals(PixelFormat.TRANSLUCENT, mNinePatchDrawable.getOpacity());
    }

    @Test
    public void testGetTransparentRegion() {
        // opaque image
        Region r = mNinePatchDrawable.getTransparentRegion();
        assertNull(r);

        mNinePatchDrawable.setBounds(0, 0, 7, 7);
        r = mNinePatchDrawable.getTransparentRegion();
        assertNull(r);

        // translucent image
        mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
        r = mNinePatchDrawable.getTransparentRegion();
        assertNull(r);

        mNinePatchDrawable.setBounds(1, 1, 7, 7);
        r = mNinePatchDrawable.getTransparentRegion();
        assertNotNull(r);
        assertEquals(new Rect(1, 1, 7, 7), r.getBounds());
    }

    @Test
    public void testGetConstantState() {
        assertNotNull(mNinePatchDrawable.getConstantState());

        ConstantState constantState = mNinePatchDrawable.getConstantState();
        // change the drawable's configuration does not affect the state's configuration
        mNinePatchDrawable.setChangingConfigurations(0xff);
        assertEquals(0, constantState.getChangingConfigurations());
        // the state's configuration refreshed when getConstantState is called.
        constantState = mNinePatchDrawable.getConstantState();
        assertEquals(0xff, constantState.getChangingConfigurations());
    }

    @Test
    public void testInflate() throws XmlPullParserException, IOException {
        int sourceWidth = 80;
        int sourceHeight = 120;
        int[] colors = new int[sourceWidth * sourceHeight];
        Bitmap bitmap = Bitmap.createBitmap(
                colors, sourceWidth, sourceHeight, Bitmap.Config.RGB_565);
        NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(
                mResources, bitmap, new byte[1000], null, "TESTNAME");

        int sourceDensity = bitmap.getDensity();
        int targetDensity = mResources.getDisplayMetrics().densityDpi;
        int targetWidth = DrawableTestUtils.scaleBitmapFromDensity(
                sourceWidth, sourceDensity, targetDensity);
        int targetHeight = DrawableTestUtils.scaleBitmapFromDensity(
                sourceHeight, sourceDensity, targetDensity);
        assertEquals(targetWidth, ninePatchDrawable.getIntrinsicWidth());
        assertEquals(targetHeight, ninePatchDrawable.getIntrinsicHeight());

        XmlResourceParser parser = mResources.getXml(R.drawable.ninepatchdrawable);
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && type != XmlPullParser.START_TAG) {
        }
        AttributeSet attrs = Xml.asAttributeSet(parser);
        ninePatchDrawable.inflate(mResources, parser, attrs);

        assertTrue(ninePatchDrawable.getPaint().isDither());
        assertTrue(sourceHeight != ninePatchDrawable.getIntrinsicHeight());
        assertTrue(sourceWidth != ninePatchDrawable.getIntrinsicWidth());
    }

    @Test
    public void testMutate() {
        NinePatchDrawable d1 =
            (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);
        NinePatchDrawable d2 =
            (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);
        NinePatchDrawable d3 =
            (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);

        // the state is not shared before mutate.
        d1.setDither(false);
        assertFalse(d1.getPaint().isDither());
        assertTrue(d2.getPaint().isDither());
        assertTrue(d3.getPaint().isDither());

        // cannot test if mutate worked, since state was not shared before
        d1.mutate();
    }

    private static final int[] DENSITY_VALUES = new int[] {
            160, 80, 320
    };

    private static final int[] DENSITY_IMAGES = new int[] {
            R.drawable.nine_patch_density
    };

    private static final int[][] DENSITY_GOLDEN_IMAGES = new int[][] {
            {
                    R.drawable.nine_patch_density_golden_160,
                    R.drawable.nine_patch_density_golden_80,
                    R.drawable.nine_patch_density_golden_320,
            }
    };

    private interface TargetDensitySetter {
        void setTargetDensity(NinePatchDrawable dr, int density);
    }

    private void verifySetTargetDensityOuter(TargetDensitySetter densitySetter) {
        final Resources res = mResources;
        final int densityDpi = res.getConfiguration().densityDpi;
        try {
            verifySetTargetDensityInner(res, DENSITY_IMAGES[0], DENSITY_VALUES, densitySetter);
        } catch (IOException | XmlPullParserException e) {
            throw new RuntimeException(e);
        } finally {
            DrawableTestUtils.setResourcesDensity(res, densityDpi);
        }
    }

    private void verifySetTargetDensityInner(Resources res, int sourceResId, int[] densities,
            TargetDensitySetter densitySetter) throws XmlPullParserException, IOException {
        final Rect tempPadding = new Rect();

        // Capture initial state at preload density.
        final int preloadDensityDpi = densities[0];
        DrawableTestUtils.setResourcesDensity(res, preloadDensityDpi);

        final NinePatchDrawable preloadedDrawable =
                (NinePatchDrawable) res.getDrawable(sourceResId).mutate();
        final int origWidth = preloadedDrawable.getIntrinsicWidth();
        final int origHeight = preloadedDrawable.getIntrinsicHeight();
        final Rect origPadding = new Rect();
        preloadedDrawable.getPadding(origPadding);

        for (int i = 1; i < densities.length; i++) {
            final int scaledDensityDpi = densities[i];
            final float scale = scaledDensityDpi / (float) preloadDensityDpi;

            final NinePatchDrawable scaledDrawable =
                    (NinePatchDrawable) res.getDrawable(sourceResId).mutate();
            densitySetter.setTargetDensity(scaledDrawable, scaledDensityDpi);

            // Sizes are rounded.
            assertEquals(Math.round(origWidth * scale), scaledDrawable.getIntrinsicWidth());
            assertEquals(Math.round(origHeight * scale), scaledDrawable.getIntrinsicHeight());

            // Padding is truncated.
            assertTrue(scaledDrawable.getPadding(tempPadding));
            assertEquals((int) (origPadding.left * scale), tempPadding.left);
            assertEquals((int) (origPadding.top * scale), tempPadding.top);
            assertEquals((int) (origPadding.right * scale), tempPadding.right);
            assertEquals((int) (origPadding.bottom * scale), tempPadding.bottom);

            // Ensure theme density is applied correctly. Unlike most
            // drawables, we don't have any loss of accuracy because density
            // changes are re-computed from the source every time.
            DrawableTestUtils.setResourcesDensity(res, preloadDensityDpi);

            final Theme t = res.newTheme();
            scaledDrawable.applyTheme(t);
            assertEquals(origWidth, scaledDrawable.getIntrinsicWidth());
            assertEquals(origHeight, scaledDrawable.getIntrinsicHeight());
            assertTrue(scaledDrawable.getPadding(tempPadding));
            assertEquals(origPadding, tempPadding);
        }
    }

    @Test
    public void testSetTargetDensity() {
        verifySetTargetDensityOuter((dr, density) -> dr.setTargetDensity(density));
    }

    @Test
    public void testSetTargetDensity_Canvas() {
        // This should be identical to calling setTargetDensity(int) with the
        // value returned by Canvas.getDensity().
        verifySetTargetDensityOuter((dr, density) -> {
            Canvas c = new Canvas();
            c.setDensity(density);
            dr.setTargetDensity(c);
        });
    }

    @Test
    public void testSetTargetDensity_DisplayMetrics() {
        // This should be identical to calling setTargetDensity(int) with the
        // value of DisplayMetrics.densityDpi.
        verifySetTargetDensityOuter((dr, density) -> {
            DisplayMetrics dm = new DisplayMetrics();
            dm.densityDpi = density;
            dr.setTargetDensity(dm);
        });
    }

    @Test
    public void testPreloadDensity() throws XmlPullParserException, IOException {
        final Resources res = mResources;
        final int densityDpi = res.getConfiguration().densityDpi;
        try {
            verifyPreloadDensityInner(res, DENSITY_IMAGES[0], DENSITY_VALUES,
                    DENSITY_GOLDEN_IMAGES[0]);
        } finally {
            DrawableTestUtils.setResourcesDensity(res, densityDpi);
        }
    }

    private void verifyPreloadDensityInner(Resources res, int sourceResId, int[] densities,
            int[] goldenResIds) throws XmlPullParserException, IOException {
        // Capture initial state at preload density.
        final int preloadDensityDpi = densities[0];
        final NinePatchDrawable preloadedDrawable = preloadedDrawable(res,
                densities[0], sourceResId);

        final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
        final int origWidth = preloadedDrawable.getIntrinsicWidth();
        final int origHeight = preloadedDrawable.getIntrinsicHeight();
        final Rect origPadding = new Rect();
        preloadedDrawable.getPadding(origPadding);

        compareOrSave(preloadedDrawable, preloadDensityDpi, sourceResId, goldenResIds[0]);

        for (int i = 1; i < densities.length; i++) {
            final int scaledDensityDpi = densities[i];
            final float scale = scaledDensityDpi / (float) preloadDensityDpi;
            DrawableTestUtils.setResourcesDensity(res, scaledDensityDpi);

            final NinePatchDrawable scaledDrawable =
                    (NinePatchDrawable) preloadedConstantState.newDrawable(res);

            assertEquals(Math.round(origWidth * scale), scaledDrawable.getIntrinsicWidth());
            assertEquals(Math.round(origHeight * scale), scaledDrawable.getIntrinsicHeight());

            // Padding is truncated.
            final Rect tempPadding = new Rect();
            assertTrue(scaledDrawable.getPadding(tempPadding));
            assertEquals((int) (origPadding.left * scale), tempPadding.left);
            assertEquals((int) (origPadding.top * scale), tempPadding.top);
            assertEquals((int) (origPadding.right * scale), tempPadding.right);
            assertEquals((int) (origPadding.bottom * scale), tempPadding.bottom);

            compareOrSave(scaledDrawable, scaledDensityDpi, sourceResId, goldenResIds[i]);

            // Ensure theme density is applied correctly. Unlike most
            // drawables, we don't have any loss of accuracy because density
            // changes are re-computed from the source every time.
            DrawableTestUtils.setResourcesDensity(res, preloadDensityDpi);

            final Theme t = res.newTheme();
            scaledDrawable.applyTheme(t);
            assertEquals(origWidth, scaledDrawable.getIntrinsicWidth());
            assertEquals(origHeight, scaledDrawable.getIntrinsicHeight());
            assertTrue(scaledDrawable.getPadding(tempPadding));
            assertEquals(origPadding, tempPadding);
        }
    }

    private static NinePatchDrawable preloadedDrawable(Resources res, int densityDpi, int sourceResId)
            throws XmlPullParserException, IOException {
        DrawableTestUtils.setResourcesDensity(res, densityDpi);
        final XmlResourceParser parser = DrawableTestUtils.getResourceParser(res, sourceResId);
        final NinePatchDrawable preloadedDrawable = new NinePatchDrawable(null);
        preloadedDrawable.inflate(res, parser, Xml.asAttributeSet(parser));
        return preloadedDrawable;
    }

    @Test
    public void testOutlinePreloadDensity() throws XmlPullParserException, IOException {
        final Resources res = mResources;
        final int densityDpi = res.getConfiguration().densityDpi;
        try {
            verifyOutlinePreloadDensityInner(res);
        } finally {
            DrawableTestUtils.setResourcesDensity(res, densityDpi);
        }
    }

    private static void verifyOutlinePreloadDensityInner(Resources res)
            throws XmlPullParserException, IOException {
        // Capture initial state at preload density.
        final int preloadDensityDpi = DENSITY_VALUES[0];
        final NinePatchDrawable preloadedDrawable = preloadedDrawable(res, preloadDensityDpi,
                R.drawable.nine_patch_odd_insets);

        final ConstantState preloadedConstantState = preloadedDrawable.getConstantState();
        final int bound = 40;
        final int expectedInset = 5;
        preloadedDrawable.setBounds(0, 0, bound, bound);
        final Outline origOutline = new Outline();
        preloadedDrawable.getOutline(origOutline);
        final Rect origOutlineRect = new Rect();
        origOutline.getRect(origOutlineRect);
        assertEquals(new Rect(expectedInset, expectedInset, bound - expectedInset,
                bound - expectedInset), origOutlineRect);
        final float origOutlineRadius = origOutline.getRadius();
        float expectedRadius = 6.8f;
        assertEquals(expectedRadius, origOutlineRadius, 0.1f);
        for (int i = 1; i < DENSITY_VALUES.length; i++) {
            final int scaledDensityDpi = DENSITY_VALUES[i];
            final float scale = scaledDensityDpi / (float) preloadDensityDpi;
            DrawableTestUtils.setResourcesDensity(res, scaledDensityDpi);
            final NinePatchDrawable scaledDrawable =
                    (NinePatchDrawable) preloadedConstantState.newDrawable(res);

            int scaledBound = (int) (bound * scale);
            scaledDrawable.setBounds(0, 0, scaledBound, scaledBound);

            final Outline tempOutline = new Outline();
            scaledDrawable.getOutline(tempOutline);
            final Rect tempOutlineRect = new Rect();
            assertTrue(tempOutline.getRect(tempOutlineRect));
            assertEquals((int) Math.ceil(origOutlineRect.left * scale), tempOutlineRect.left);
            assertEquals((int) Math.ceil(origOutlineRect.top * scale), tempOutlineRect.top);
            assertEquals((int) Math.floor(origOutlineRect.right * scale), tempOutlineRect.right);
            assertEquals((int) Math.floor(origOutlineRect.bottom * scale), tempOutlineRect.bottom);
            assertEquals(origOutlineRadius * scale, tempOutline.getRadius(), 0.1f);
        }
    }

    private void verifyColorFillRect(Bitmap bmp, int x, int y, int w, int h, int color) {
        for (int i = x; i < x + w; i++) {
            for (int j = y; j < y + h; j++) {
                assertEquals(color, bmp.getPixel(i, j));
            }
        }
    }

    private NinePatchDrawable getNinePatchDrawable(int resId) {
        // jump through hoops to avoid scaling the tiny ninepatch, which would skew the results
        // depending on device density
        Bitmap bitmap = getBitmapUnscaled(resId);
        NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null);
        return new NinePatchDrawable(mResources, np);
    }

    private Bitmap getBitmapUnscaled(int resId) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inDensity = opts.inTargetDensity = mResources.getDisplayMetrics().densityDpi;
        Bitmap bitmap = BitmapFactory.decodeResource(mResources, resId, opts);
        return bitmap;
    }

    private void compareOrSave(Drawable dr, int densityDpi, int sourceResId, int goldenResId) {
        final int width = dr.getIntrinsicWidth();
        final int height = dr.getIntrinsicHeight();
        final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setDensity(0);

        final Canvas canvas = new Canvas(bitmap);
        dr.setBounds(0, 0, width, height);
        dr.draw(canvas);

        if (DBG_DUMP_PNG) {
            saveGoldenImage(bitmap, sourceResId, densityDpi);
        } else {
            final Bitmap golden = BitmapFactory.decodeResource(mResources, goldenResId);
            DrawableTestUtils.compareImages(densityDpi + " dpi", golden, bitmap,
                    PIXEL_ERROR_THRESHOLD, PIXEL_ERROR_COUNT_THRESHOLD, 0 /* tolerance */);
        }
    }

    private void saveGoldenImage(Bitmap bitmap, int sourceResId, int densityDpi) {
        // Save the image to the disk.
        FileOutputStream out = null;

        try {
            final String outputFolder = "/sdcard/temp/";
            final File folder = new File(outputFolder);
            if (!folder.exists()) {
                folder.mkdir();
            }

            final String sourceFilename = new File(mResources.getString(sourceResId)).getName();
            final String sourceTitle = sourceFilename.substring(0, sourceFilename.lastIndexOf("."));
            final String outputTitle = sourceTitle + "_golden_" + densityDpi;
            final String outputFilename = outputFolder + outputTitle + ".png";
            final File outputFile = new File(outputFilename);
            if (!outputFile.exists()) {
                outputFile.createNewFile();
            }

            out = new FileOutputStream(outputFile, false);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
