NinePatch.cpp revision 4c5efe9290543b723b76a8bd48518da1ae1dcb26
18cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn/*
28cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn**
38cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** Copyright 2006, The Android Open Source Project
48cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn**
58cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** Licensed under the Apache License, Version 2.0 (the "License");
68cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** you may not use this file except in compliance with the License.
78cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** You may obtain a copy of the License at
88cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn**
98cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn**     http://www.apache.org/licenses/LICENSE-2.0
108cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn**
118cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** Unless required by applicable law or agreed to in writing, software
128cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** distributed under the License is distributed on an "AS IS" BASIS,
138cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** See the License for the specific language governing permissions and
158cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn** limitations under the License.
168cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn*/
178cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn
188cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn#define LOG_TAG "9patch"
198cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn#define LOG_NDEBUG 1
208cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn
21b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
228cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn#include <utils/Log.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24a35778c799e8073a42b9e22191bde9d838327ab7John Reck#include <ResourceCache.h>
25e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
266ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
278872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "Canvas.h"
2811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn#include "SkCanvas.h"
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkRegion.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
324c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger#include "utils/NinePatch.h"
334c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h"
35ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy/**
40e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * IMPORTANT NOTE: 9patch chunks can be manipuated either as an array of bytes
41e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * or as a Res_png_9patch instance. It is important to note that the size of the
42e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * array required to hold a 9patch chunk is greater than sizeof(Res_png_9patch).
43e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * The code below manipulates chunks as Res_png_9patch* types to draw and as
44e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy * int8_t* to allocate and free the backing storage.
45e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy */
46e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass SkNinePatchGlue {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
49e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (NULL == obj) {
5136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            return JNI_FALSE;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (env->GetArrayLength(obj) < (int)sizeof(Res_png_9patch)) {
5436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            return JNI_FALSE;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const jbyte* array = env->GetByteArrayElements(obj, 0);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (array != NULL) {
58e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            const Res_png_9patch* chunk = reinterpret_cast<const Res_png_9patch*>(array);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int8_t wasDeserialized = chunk->wasDeserialized;
60e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array), JNI_ABORT);
6136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            return (wasDeserialized != -1) ? JNI_TRUE : JNI_FALSE;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return JNI_FALSE;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
667c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    static jlong validateNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) {
67e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        size_t chunkSize = env->GetArrayLength(obj);
68e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        if (chunkSize < (int) (sizeof(Res_png_9patch))) {
6969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            jniThrowRuntimeException(env, "Array too small for chunk.");
70e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            return NULL;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
73e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        int8_t* storage = new int8_t[chunkSize];
74e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        // This call copies the content of the jbyteArray
75e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        env->GetByteArrayRegion(obj, 0, chunkSize, reinterpret_cast<jbyte*>(storage));
76e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        // Deserialize in place, return the array we just allocated
7736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return reinterpret_cast<jlong>(Res_png_9patch::deserialize(storage));
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    static void finalize(JNIEnv* env, jobject, jlong patchHandle) {
8136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        int8_t* patch = reinterpret_cast<int8_t*>(patchHandle);
82a35778c799e8073a42b9e22191bde9d838327ab7John Reck        if (android::uirenderer::ResourceCache::hasInstance()) {
83e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy            Res_png_9patch* p = (Res_png_9patch*) patch;
84a35778c799e8073a42b9e22191bde9d838327ab7John Reck            android::uirenderer::ResourceCache::getInstance().destructor(p);
85a2732a2bf98f7dbd063f4e5679f5b8bfcbec2698John Reck        } else {
86a2732a2bf98f7dbd063f4e5679f5b8bfcbec2698John Reck            delete[] patch;
87e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        }
88e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy    }
89e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
907c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap,
9136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            jlong chunkHandle, jobject boundsRect) {
9236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
93e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        SkASSERT(chunk);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SkASSERT(boundsRect);
9569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
967c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        SkBitmap bitmap;
977c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
98e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        SkRect bounds;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
100e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
101e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy        SkRegion* region = NULL;
1024c5efe9290543b723b76a8bd48518da1ae1dcb26Derek Sollenberger        NinePatch::Draw(NULL, bounds, bitmap, *chunk, NULL, &region);
103e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy
10436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        return reinterpret_cast<jlong>(region);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////////
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gNinePatchMethods[] = {
1127c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
1137c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    { "validateNinePatchChunk", "([B)J",
1147c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            (void*) SkNinePatchGlue::validateNinePatchChunk },
1157c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize },
1167c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck    { "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J",
1177c103a36f60b690e3fe83c40210e1cb0c76bba43John Reck            (void*) SkNinePatchGlue::getTransparentRegion }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
120e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guyint register_android_graphics_NinePatch(JNIEnv* env) {
121ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env,
122ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            "android/graphics/NinePatch", gNinePatchMethods, NELEM(gNinePatchMethods));
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
124