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> 22dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Canvas.h> 23dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h> 248cae124af2142687a6833dbaab8a43df6dd67b43Dianne Hackborn#include <utils/Log.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26a35778c799e8073a42b9e22191bde9d838327ab7John Reck#include <ResourceCache.h> 27e3b0a0117a2ab4118f868a731b238fe8f2430276Romain Guy 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, ®ion); 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 11176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const 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