NinePatch.java revision f296dca95f09be9832b5dcc79717986525d2b6cb
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;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The NinePatch class permits drawing a bitmap in nine sections.
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The four corners are unscaled; the four edges are scaled in one axis,
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the middle is scaled in both axes. Normally, the middle is
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * transparent so that the patch can provide a selection about a rectangle.
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Essentially, it allows the creation of custom graphics that will scale the
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * way that you define, when content added within the image exceeds the normal
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bounds of the graphic. For a thorough explanation of a NinePatch image,
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * read the discussion in the
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Graphics</a> document.
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-Patch</a>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * tool offers an extremely handy way to create your NinePatch images,
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * using a WYSIWYG graphics editor.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p>
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class NinePatch {
38deba785f122a47915756ffd991f5540d952cf937Romain Guy    private final Bitmap mBitmap;
393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * @hide
413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    public final byte[] mChunk;
43deba785f122a47915756ffd991f5540d952cf937Romain Guy    private Paint mPaint;
44deba785f122a47915756ffd991f5540d952cf937Romain Guy    private String mSrcName;  // Useful for debugging
45f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy
46f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    /**
47f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     * Create a drawable projection from a bitmap to nine patches.
48f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     *
49f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     * @param bitmap    The bitmap describing the patches.
50f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     * @param chunk     The 9-patch data chunk describing how the underlying
51f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     *                  bitmap is split apart and drawn.
52f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy     */
53f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    public NinePatch(Bitmap bitmap, byte[] chunk) {
54f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy        this(bitmap, chunk, null);
55f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    }
56f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a drawable projection from a bitmap to nine patches.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bitmap    The bitmap describing the patches.
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param chunk     The 9-patch data chunk describing how the underlying
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                  bitmap is split apart and drawn.
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param srcName   The name of the source for the bitmap. Might be null.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmap = bitmap;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mChunk = chunk;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSrcName = srcName;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        validateNinePatchChunk(mBitmap.ni(), chunk);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NinePatch(NinePatch patch) {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBitmap = patch.mBitmap;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mChunk = patch.mChunk;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSrcName = patch.mSrcName;
7954285f2cbfb6e307d594ca264f7230b4e1e3cdcePhil Dubach        if (patch.mPaint != null) {
8054285f2cbfb6e307d594ca264f7230b4e1e3cdcePhil Dubach            mPaint = new Paint(patch.mPaint);
8154285f2cbfb6e307d594ca264f7230b4e1e3cdcePhil Dubach        }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        validateNinePatchChunk(mBitmap.ni(), mChunk);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPaint(Paint p) {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPaint = p;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
883b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
893b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
903b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * @hide
913b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
923b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    public Bitmap getBitmap() {
933b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        return mBitmap;
943b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Draw a bitmap of nine patches.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param location  Where to draw the bitmap.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas, RectF location) {
103f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        canvas.drawPatch(this, location, mPaint);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
105f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Draw a bitmap of nine patches.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param location  Where to draw the bitmap.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas, Rect location) {
113f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        canvas.drawPatch(this, location, mPaint);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Draw a bitmap of nine patches.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param location  Where to draw the bitmap.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param paint     The Paint to draw through.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void draw(Canvas canvas, Rect location, Paint paint) {
124f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        canvas.drawPatch(this, location, paint);
125f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    }
126f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy
127f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    /**
128f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy     * @hide
129f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy     */
130f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    void drawSoftware(Canvas canvas, RectF location, Paint paint) {
131f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mChunk,
132f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
133f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    }
134f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy
135f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    /**
136f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy     * @hide
137f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy     */
138f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy    void drawSoftware(Canvas canvas, Rect location, Paint paint) {
139f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mChunk,
140f296dca95f09be9832b5dcc79717986525d2b6cbRomain Guy                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
14411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Return the underlying bitmap's density, as per
14511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * {@link Bitmap#getDensity() Bitmap.getDensity()}.
14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
14711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    public int getDensity() {
14811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return mBitmap.mDensity;
14911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
15011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWidth() {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmap.getWidth();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getHeight() {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmap.getHeight();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean hasAlpha() {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBitmap.hasAlpha();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final Region getTransparentRegion(Rect location) {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int r = nativeGetTransparentRegion(mBitmap.ni(), mChunk, location);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return r != 0 ? new Region(r) : null;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native static boolean isNinePatchChunk(byte[] chunk);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void validateNinePatchChunk(int bitmap, byte[] chunk);
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
17211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                                          byte[] c, int paint_instance_or_null,
17311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                                          int destDensity, int srcDensity);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
17511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                                          byte[] c, int paint_instance_or_null,
17611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                                          int destDensity, int srcDensity);
177f3187b7df158d2de36955ddcc666ba4b8544a2ceRomain Guy    private static native int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location);
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
179