Home | History | Annotate | Download | only in graphics
      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