1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics; 18 19 20 /** 21 * The NinePatch class permits drawing a bitmap in nine or more sections. 22 * Essentially, it allows the creation of custom graphics that will scale the 23 * way that you define, when content added within the image exceeds the normal 24 * bounds of the graphic. For a thorough explanation of a NinePatch image, 25 * read the discussion in the 26 * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D 27 * Graphics</a> document. 28 * <p> 29 * The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-Patch</a> 30 * tool offers an extremely handy way to create your NinePatch images, 31 * using a WYSIWYG graphics editor. 32 * </p> 33 */ 34 public class NinePatch { 35 private final Bitmap mBitmap; 36 37 /** 38 * Used by native code. This pointer is an instance of Res_png_9patch*. 39 * 40 * @hide 41 */ 42 public final int mNativeChunk; 43 44 private Paint mPaint; 45 private String mSrcName; 46 47 /** 48 * Create a drawable projection from a bitmap to nine patches. 49 * 50 * @param bitmap The bitmap describing the patches. 51 * @param chunk The 9-patch data chunk describing how the underlying bitmap 52 * is split apart and drawn. 53 */ 54 public NinePatch(Bitmap bitmap, byte[] chunk) { 55 this(bitmap, chunk, null); 56 } 57 58 /** 59 * Create a drawable projection from a bitmap to nine patches. 60 * 61 * @param bitmap The bitmap describing the patches. 62 * @param chunk The 9-patch data chunk describing how the underlying 63 * bitmap is split apart and drawn. 64 * @param srcName The name of the source for the bitmap. Might be null. 65 */ 66 public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) { 67 mBitmap = bitmap; 68 mSrcName = srcName; 69 mNativeChunk = validateNinePatchChunk(mBitmap.ni(), chunk); 70 } 71 72 /** 73 * @hide 74 */ 75 public NinePatch(NinePatch patch) { 76 mBitmap = patch.mBitmap; 77 mSrcName = patch.mSrcName; 78 if (patch.mPaint != null) { 79 mPaint = new Paint(patch.mPaint); 80 } 81 // No need to validate the 9patch chunk again, it was done by 82 // the instance we're copying from 83 mNativeChunk = patch.mNativeChunk; 84 } 85 86 @Override 87 protected void finalize() throws Throwable { 88 try { 89 nativeFinalize(mNativeChunk); 90 } finally { 91 super.finalize(); 92 } 93 } 94 95 /** 96 * Returns the name of this NinePatch object if one was specified 97 * when calling the constructor. 98 */ 99 public String getName() { 100 return mSrcName; 101 } 102 103 /** 104 * Returns the paint used to draw this NinePatch. The paint can be null. 105 * 106 * @see #setPaint(Paint) 107 * @see #draw(Canvas, Rect) 108 * @see #draw(Canvas, RectF) 109 */ 110 public Paint getPaint() { 111 return mPaint; 112 } 113 114 /** 115 * Sets the paint to use when drawing the NinePatch. 116 * 117 * @param p The paint that will be used to draw this NinePatch. 118 * 119 * @see #getPaint() 120 * @see #draw(Canvas, Rect) 121 * @see #draw(Canvas, RectF) 122 */ 123 public void setPaint(Paint p) { 124 mPaint = p; 125 } 126 127 /** 128 * Returns the bitmap used to draw this NinePatch. 129 */ 130 public Bitmap getBitmap() { 131 return mBitmap; 132 } 133 134 /** 135 * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}. 136 * 137 * @param canvas A container for the current matrix and clip used to draw the NinePatch. 138 * @param location Where to draw the NinePatch. 139 */ 140 public void draw(Canvas canvas, RectF location) { 141 canvas.drawPatch(this, location, mPaint); 142 } 143 144 /** 145 * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}. 146 * 147 * @param canvas A container for the current matrix and clip used to draw the NinePatch. 148 * @param location Where to draw the NinePatch. 149 */ 150 public void draw(Canvas canvas, Rect location) { 151 canvas.drawPatch(this, location, mPaint); 152 } 153 154 /** 155 * Draws the NinePatch. This method will ignore the paint returned 156 * by {@link #getPaint()} and use the specified paint instead. 157 * 158 * @param canvas A container for the current matrix and clip used to draw the NinePatch. 159 * @param location Where to draw the NinePatch. 160 * @param paint The Paint to draw through. 161 */ 162 public void draw(Canvas canvas, Rect location, Paint paint) { 163 canvas.drawPatch(this, location, paint); 164 } 165 166 void drawSoftware(Canvas canvas, RectF location, Paint paint) { 167 nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk, 168 paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity); 169 } 170 171 void drawSoftware(Canvas canvas, Rect location, Paint paint) { 172 nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk, 173 paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity); 174 } 175 176 /** 177 * Return the underlying bitmap's density, as per 178 * {@link Bitmap#getDensity() Bitmap.getDensity()}. 179 */ 180 public int getDensity() { 181 return mBitmap.mDensity; 182 } 183 184 /** 185 * Returns the intrinsic width, in pixels, of this NinePatch. This is equivalent 186 * to querying the width of the underlying bitmap returned by {@link #getBitmap()}. 187 */ 188 public int getWidth() { 189 return mBitmap.getWidth(); 190 } 191 192 /** 193 * Returns the intrinsic height, in pixels, of this NinePatch. This is equivalent 194 * to querying the height of the underlying bitmap returned by {@link #getBitmap()}. 195 */ 196 public int getHeight() { 197 return mBitmap.getHeight(); 198 } 199 200 /** 201 * Indicates whether this NinePatch contains transparent or translucent pixels. 202 * This is equivalent to calling <code>getBitmap().hasAlpha()</code> on this 203 * NinePatch. 204 */ 205 public final boolean hasAlpha() { 206 return mBitmap.hasAlpha(); 207 } 208 209 /** 210 * Returns a {@link Region} representing the parts of the NinePatch that are 211 * completely transparent. 212 * 213 * @param bounds The location and size of the NinePatch. 214 * 215 * @return null if the NinePatch has no transparent region to 216 * report, else a {@link Region} holding the parts of the specified bounds 217 * that are transparent. 218 */ 219 public final Region getTransparentRegion(Rect bounds) { 220 int r = nativeGetTransparentRegion(mBitmap.ni(), mNativeChunk, bounds); 221 return r != 0 ? new Region(r) : null; 222 } 223 224 /** 225 * Verifies that the specified byte array is a valid 9-patch data chunk. 226 * 227 * @param chunk A byte array representing a 9-patch data chunk. 228 * 229 * @return True if the specified byte array represents a 9-patch data chunk, 230 * false otherwise. 231 */ 232 public native static boolean isNinePatchChunk(byte[] chunk); 233 234 /** 235 * Validates the 9-patch chunk and throws an exception if the chunk is invalid. 236 * If validation is successful, this method returns a native Res_png_9patch* 237 * object used by the renderers. 238 */ 239 private static native int validateNinePatchChunk(int bitmap, byte[] chunk); 240 private static native void nativeFinalize(int chunk); 241 private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance, 242 int c, int paint_instance_or_null, int destDensity, int srcDensity); 243 private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance, 244 int c, int paint_instance_or_null, int destDensity, int srcDensity); 245 private static native int nativeGetTransparentRegion(int bitmap, int chunk, Rect location); 246 } 247