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