19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
211557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.Bitmap;
221557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.BitmapFactory;
231557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.Canvas;
241557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.ColorFilter;
25bbd51f1e360b22eece1d74bd65c7e6a0b59dee59Philip Milneimport android.graphics.Insets;
261557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.NinePatch;
271557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.Paint;
281557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.PixelFormat;
291557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.Rect;
301557fd7809078e421f751efc7d2539b3efdc54b2Philip Milneimport android.graphics.Region;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
3211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackbornimport android.util.DisplayMetrics;
333f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglioimport android.util.LayoutDirection;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
421557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne *
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A resizeable bitmap, with stretchable areas that you define. This type of image
4461fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * is defined in a .png file with a special format.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4661fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <div class="special reference">
4761fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <h3>Developer Guides</h3>
4861fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <p>For more information about how to use a NinePatchDrawable, read the
4961fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">
5061fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * Canvas and Drawables</a> developer guide. For information about creating a NinePatch image
5161fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * file using the draw9patch tool, see the
5261fd1e8d8c3ccf2d6b7d4af1c19e8f0988d5a1ecJoe Fernandez * <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> tool guide.</p></div>
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class NinePatchDrawable extends Drawable {
55211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed    // dithering helps a lot, and is pretty cheap, so default is true
56f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    private static final boolean DEFAULT_DITHER = false;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private NinePatchState mNinePatchState;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private NinePatch mNinePatch;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Rect mPadding;
607b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne    private Insets mOpticalInsets = Insets.NONE;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mPaint;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMutated;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
6511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
6611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    // These are scaled to match the target density.
6711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private int mBitmapWidth;
6811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private int mBitmapHeight;
691557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NinePatchDrawable() {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
7411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from raw nine-patch data, not dealing with density.
7511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)}
7611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * to ensure that the drawable has correctly set its target density.
7711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
784a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
80c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
821557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
8311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
8411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from raw nine-patch data, setting initial target density
8511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * based on the display metrics of the resources.
8611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
8711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
8811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            Rect padding, String srcName) {
89c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
90c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mNinePatchState.mTargetDensity = mTargetDensity;
9111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
921557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
931557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    /**
941557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * Create drawable from raw nine-patch data, setting initial target density
951557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * based on the display metrics of the resources.
961557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     *
971557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * @hide
981557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     */
991557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
1007b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne            Rect padding, Rect opticalInsets, String srcName) {
1017b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets), res);
1021557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne        mNinePatchState.mTargetDensity = mTargetDensity;
1031557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    }
1041557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
10511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
10611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from existing nine-patch, not dealing with density.
10711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
10811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * to ensure that the drawable has correctly set its target density.
10911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
1104a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NinePatchDrawable(NinePatch patch) {
112e57b7b09b198699adea91b6f9729007fda00834eCary Clark        this(new NinePatchState(patch, new Rect()), null);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
11611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Create drawable from existing nine-patch, setting initial target density
11711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * based on the display metrics of the resources.
11811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
11911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public NinePatchDrawable(Resources res, NinePatch patch) {
120e57b7b09b198699adea91b6f9729007fda00834eCary Clark        this(new NinePatchState(patch, new Rect()), res);
121c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mNinePatchState.mTargetDensity = mTargetDensity;
12211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
12311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
124c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private void setNinePatchState(NinePatchState state, Resources res) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNinePatchState = state;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNinePatch = state.mNinePatch;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPadding = state.mPadding;
128c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        mTargetDensity = res != null ? res.getDisplayMetrics().densityDpi
129c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn                : state.mTargetDensity;
1309db91243c5ace4421091557b76a0b1cbd2312fecRomain Guy        //noinspection PointlessBooleanExpression
1319db91243c5ace4421091557b76a0b1cbd2312fecRomain Guy        if (state.mDither != DEFAULT_DITHER) {
132211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed            // avoid calling the setter unless we need to, since it does a
133211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed            // lazy allocation of a paint
134211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed            setDither(state.mDither);
135211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed        }
1363f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        setAutoMirrored(state.mAutoMirrored);
13711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (mNinePatch != null) {
13811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            computeBitmapSize();
13911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
14311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Set the density scale at which this drawable will be rendered. This
14411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * method assumes the drawable will be rendered at the same density as the
14511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * specified canvas.
14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
14711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param canvas The Canvas from which the density scale must be obtained.
14811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
14911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
15011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
15111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
15211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(Canvas canvas) {
15311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        setTargetDensity(canvas.getDensity());
15411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
15511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
15611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
15711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Set the density scale at which this drawable will be rendered.
15811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
15911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param metrics The DisplayMetrics indicating the density scale for this drawable.
16011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
16111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
16211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
16311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
16411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(DisplayMetrics metrics) {
1659891e1fce5f29d0421d34aa481037417bd70853dChet Haase        setTargetDensity(metrics.densityDpi);
16611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
16711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
16811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
16911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Set the density at which this drawable will be rendered.
17011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
17111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param density The density scale for this drawable.
17211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
17311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#setDensity(int)
17411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.graphics.Bitmap#getDensity()
17511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
17611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public void setTargetDensity(int density) {
1779891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (density != mTargetDensity) {
1789891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
1799891e1fce5f29d0421d34aa481037417bd70853dChet Haase            if (mNinePatch != null) {
1809891e1fce5f29d0421d34aa481037417bd70853dChet Haase                computeBitmapSize();
1819891e1fce5f29d0421d34aa481037417bd70853dChet Haase            }
1829891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
18311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
18411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
18511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
1865f49c3023a512efbef8bc9515d310c7a72be4af2Romain Guy    private static Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
1877a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne        int left = Bitmap.scaleFromDensity(insets.left, sdensity, tdensity);
1887a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne        int top = Bitmap.scaleFromDensity(insets.top, sdensity, tdensity);
1897a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne        int right = Bitmap.scaleFromDensity(insets.right, sdensity, tdensity);
1907a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne        int bottom = Bitmap.scaleFromDensity(insets.bottom, sdensity, tdensity);
1917a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne        return Insets.of(left, top, right, bottom);
1927a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne    }
1937a23b49a8ceb07d3fa12c45fd42cd16131fd746aPhilip Milne
19411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private void computeBitmapSize() {
19511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        final int sdensity = mNinePatch.getDensity();
19611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        final int tdensity = mTargetDensity;
197b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn        if (sdensity == tdensity) {
198b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn            mBitmapWidth = mNinePatch.getWidth();
199b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn            mBitmapHeight = mNinePatch.getHeight();
2007b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne            mOpticalInsets = mNinePatchState.mOpticalInsets;
201b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn        } else {
202f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy            mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(), sdensity, tdensity);
203f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy            mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(), sdensity, tdensity);
204279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova            if (mNinePatchState.mPadding != null && mPadding != null) {
205279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                Rect dest = mPadding;
206279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                Rect src = mNinePatchState.mPadding;
207279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                if (dest == src) {
208279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                    mPadding = dest = new Rect(src);
209279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                }
210279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                dest.left = Bitmap.scaleFromDensity(src.left, sdensity, tdensity);
211279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                dest.top = Bitmap.scaleFromDensity(src.top, sdensity, tdensity);
212279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                dest.right = Bitmap.scaleFromDensity(src.right, sdensity, tdensity);
213279d006b1d194c597a4c6b0a72f66ea6128851faSonia Serafimova                dest.bottom = Bitmap.scaleFromDensity(src.bottom, sdensity, tdensity);
214b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn            }
2157b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne            mOpticalInsets = scaleFromDensity(mNinePatchState.mOpticalInsets, sdensity, tdensity);
216b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn        }
21711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas) {
2213f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        final Rect bounds = getBounds();
222ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        final boolean needsMirroring = needsMirroring();
223ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        if (needsMirroring) {
2243f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            canvas.save();
2253f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            // Mirror the 9patch
2263f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            canvas.translate(bounds.right - bounds.left, 0);
2273f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            canvas.scale(-1.0f, 1.0f);
2283f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
2293f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        mNinePatch.draw(canvas, bounds, mPaint);
230ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        if (needsMirroring) {
2313f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            canvas.restore();
2323f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChangingConfigurations() {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.getChangingConfigurations() | mNinePatchState.mChangingConfigurations;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2391557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPadding(Rect padding) {
242ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        if (needsMirroring()) {
243ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey            padding.set(mPadding.right, mPadding.top, mPadding.left, mPadding.bottom);
244ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        } else {
245ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey            padding.set(mPadding);
246ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        }
247f7a93ef3847258157d144dfefaa5757128cc807dFabrice Di Meglio        return (padding.left | padding.top | padding.right | padding.bottom) != 0;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2501557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    /**
2511557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     * @hide
2521557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne     */
2531557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    @Override
2547b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne    public Insets getOpticalInsets() {
255ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        if (needsMirroring()) {
256ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey            return Insets.of(mOpticalInsets.right, mOpticalInsets.top, mOpticalInsets.right,
257ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey                    mOpticalInsets.bottom);
258ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        } else {
259ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey            return mOpticalInsets;
260ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        }
2611557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne    }
2621557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
26568d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        if (mPaint == null && alpha == 0xFF) {
26668d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            // Fast common case -- leave at normal alpha.
26768d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            return;
26868d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getPaint().setAlpha(alpha);
2709891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2721557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
274b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
275b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        if (mPaint == null) {
276b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase            // Fast common case -- normal alpha.
277b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase            return 0xFF;
278b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        }
279b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return getPaint().getAlpha();
280b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
281b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
282b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setColorFilter(ColorFilter cf) {
28468d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        if (mPaint == null && cf == null) {
28568d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            // Fast common case -- leave at no color filter.
28668d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            return;
28768d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getPaint().setColorFilter(cf);
2899891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
294f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        //noinspection PointlessBooleanExpression
29568d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        if (mPaint == null && dither == DEFAULT_DITHER) {
29668d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            // Fast common case -- leave at default dither.
29768d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn            return;
29868d91733c873d80eb107b6e7a46228d9397b373eDianne Hackborn        }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getPaint().setDither(dither);
3009891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3043f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public void setAutoMirrored(boolean mirrored) {
3053f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        mNinePatchState.mAutoMirrored = mirrored;
3063f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
3073f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
308ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey    private boolean needsMirroring() {
309ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
310ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey    }
311ee3e1603fdbbe24b0cbf3cb85c456696cf3b7941Jeff Sharkey
3123f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
3133f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    public boolean isAutoMirrored() {
3143f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        return mNinePatchState.mAutoMirrored;
3153f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    }
3163f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
3173f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio    @Override
318d9512a30d8e5c7780c3faf2fa59c076010f67b9eMike Reed    public void setFilterBitmap(boolean filter) {
3194a123c4d69a1a73d0e16834700c3fe95034fe66eRomain Guy        getPaint().setFilterBitmap(filter);
3204a123c4d69a1a73d0e16834700c3fe95034fe66eRomain Guy        invalidateSelf();
321d9512a30d8e5c7780c3faf2fa59c076010f67b9eMike Reed    }
322d9512a30d8e5c7780c3faf2fa59c076010f67b9eMike Reed
323d9512a30d8e5c7780c3faf2fa59c076010f67b9eMike Reed    @Override
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.inflate(r, parser, attrs);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.NinePatchDrawable);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int id = a.getResourceId(com.android.internal.R.styleable.NinePatchDrawable_src, 0);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id == 0) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(parser.getPositionDescription() +
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ": <nine-patch> requires a valid src attribute");
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean dither = a.getBoolean(
337f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy                com.android.internal.R.styleable.NinePatchDrawable_dither, DEFAULT_DITHER);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final BitmapFactory.Options options = new BitmapFactory.Options();
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dither) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            options.inDither = false;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
342908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
344ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani        final Rect padding = new Rect();
3457b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne        final Rect opticalInsets = new Rect();
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bitmap = null;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TypedValue value = new TypedValue();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final InputStream is = r.openRawResource(id, value);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            is.close();
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Ignore
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bitmap == null) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(parser.getPositionDescription() +
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ": <nine-patch> requires a valid src attribute");
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (bitmap.getNinePatchChunk() == null) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new XmlPullParserException(parser.getPositionDescription() +
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ": <nine-patch> requires a valid 9-patch source image");
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3673f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        final boolean automirrored = a.getBoolean(
3683f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                com.android.internal.R.styleable.NinePatchDrawable_autoMirrored, false);
3693f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio
370f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        setNinePatchState(new NinePatchState(new NinePatch(bitmap, bitmap.getNinePatchChunk()),
3713f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                padding, opticalInsets, dither, automirrored), r);
37211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mNinePatchState.mTargetDensity = mTargetDensity;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Paint getPaint() {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPaint == null) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPaint = new Paint();
380211db4a2874f1a2d0e7a8cb8d33e81fa08801763Mike Reed            mPaint.setDither(DEFAULT_DITHER);
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPaint;
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieves the width of the source .png file (before resizing).
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
39011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapWidth;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieves the height of the source .png file (before resizing).
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
39811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapHeight;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumWidth() {
40311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapWidth;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMinimumHeight() {
40811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmapHeight;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * value of OPAQUE or TRANSLUCENT.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNinePatch.hasAlpha() || (mPaint != null && mPaint.getAlpha() < 255) ?
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Region getTransparentRegion() {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNinePatch.getTransparentRegion(getBounds());
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4251557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
4286efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mNinePatchState.mChangingConfigurations = getChangingConfigurations();
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNinePatchState;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNinePatchState = new NinePatchState(mNinePatchState);
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNinePatch = mNinePatchState.mNinePatch;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    final static class NinePatchState extends ConstantState {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final NinePatch mNinePatch;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect mPadding;
4457b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne        final Insets mOpticalInsets;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean mDither;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mChangingConfigurations;
44811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
4493f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        boolean mAutoMirrored;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NinePatchState(NinePatch ninePatch, Rect padding) {
4523f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            this(ninePatch, padding, new Rect(), DEFAULT_DITHER, false);
4531557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne        }
4541557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
4557b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne        NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets) {
4563f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            this(ninePatch, padding, opticalInsets, DEFAULT_DITHER, false);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4593f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio        NinePatchState(NinePatch ninePatch, Rect rect, Rect opticalInsets, boolean dither,
4603f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio                       boolean autoMirror) {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNinePatch = ninePatch;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPadding = rect;
4637b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne            mOpticalInsets = Insets.of(opticalInsets);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDither = dither;
4653f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            mAutoMirrored = autoMirror;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4681557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne        // Copy constructor
4691557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NinePatchState(NinePatchState state) {
471f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy            // Note we don't copy the nine patch because it is immutable.
472f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy            mNinePatch = state.mNinePatch;
473b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn            // Note we don't copy the padding because it is immutable.
474b8a9f12802ca5d1738a098a1769a8ed7959f248bDianne Hackborn            mPadding = state.mPadding;
4757b7578184567f4e4f0740ce935cc192765410ccaPhilip Milne            mOpticalInsets = state.mOpticalInsets;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDither = state.mDither;
47711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            mChangingConfigurations = state.mChangingConfigurations;
47811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            mTargetDensity = state.mTargetDensity;
4793f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aaFabrice Di Meglio            mAutoMirrored = state.mAutoMirrored;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        public Bitmap getBitmap() {
4843b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy            return mNinePatch.getBitmap();
4853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        }
4863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
4873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        @Override
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
489c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new NinePatchDrawable(this, null);
490c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
4911557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
492c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
493c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
494c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn            return new NinePatchDrawable(this, res);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4961557fd7809078e421f751efc7d2539b3efdc54b2Philip Milne
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getChangingConfigurations() {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mChangingConfigurations;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
503c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn    private NinePatchDrawable(NinePatchState state, Resources res) {
504c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        setNinePatchState(state, res);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
507