NinePatch.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1#include <utils/ResourceTypes.h> 2 3#include "SkRegion.h" 4#include "GraphicsJNI.h" 5 6#include "JNIHelp.h" 7 8extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, 9 const SkBitmap& bitmap, const android::Res_png_9patch& chunk, 10 const SkPaint* paint, SkRegion** outRegion); 11 12using namespace android; 13 14class SkNinePatchGlue { 15public: 16 static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) 17 { 18 if (NULL == obj) { 19 return false; 20 } 21 if (env->GetArrayLength(obj) < (int)sizeof(Res_png_9patch)) { 22 return false; 23 } 24 const jbyte* array = env->GetByteArrayElements(obj, 0); 25 if (array != NULL) { 26 const Res_png_9patch* chunk = 27 reinterpret_cast<const Res_png_9patch*>(array); 28 int8_t wasDeserialized = chunk->wasDeserialized; 29 env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array), 30 JNI_ABORT); 31 return wasDeserialized != -1; 32 } 33 return false; 34 } 35 36 static void validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj) 37 { 38 if (env->GetArrayLength(obj) < (int) (sizeof(Res_png_9patch))) { 39 jniThrowException(env, "java/lang/RuntimeException", 40 "Array too small for chunk."); 41 return; 42 } 43 44 // XXX Also check that dimensions are correct. 45 } 46 47 static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, 48 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 49 { 50 size_t chunkSize = env->GetArrayLength(chunkObj); 51 void* storage = alloca(chunkSize); 52 env->GetByteArrayRegion(chunkObj, 0, chunkSize, 53 reinterpret_cast<jbyte*>(storage)); 54 if (!env->ExceptionCheck()) { 55 // need to deserialize the chunk 56 Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage); 57 assert(chunkSize == chunk->serializedSize()); 58 // this relies on deserialization being done in place 59 Res_png_9patch::deserialize(chunk); 60 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL); 61 } 62 } 63 64 static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF, 65 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 66 { 67 SkASSERT(canvas); 68 SkASSERT(boundsRectF); 69 SkASSERT(bitmap); 70 SkASSERT(chunkObj); 71 // paint is optional 72 73 SkRect bounds; 74 GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds); 75 76 draw(env, canvas, bounds, bitmap, chunkObj, paint); 77 } 78 79 static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect, 80 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 81 { 82 SkASSERT(canvas); 83 SkASSERT(boundsRect); 84 SkASSERT(bitmap); 85 SkASSERT(chunkObj); 86 // paint is optional 87 88 SkRect bounds; 89 GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); 90 draw(env, canvas, bounds, bitmap, chunkObj, paint); 91 } 92 93 static jint getTransparentRegion(JNIEnv* env, jobject, 94 const SkBitmap* bitmap, jbyteArray chunkObj, 95 jobject boundsRect) 96 { 97 SkASSERT(bitmap); 98 SkASSERT(chunkObj); 99 SkASSERT(boundsRect); 100 101 SkRect bounds; 102 GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); 103 size_t chunkSize = env->GetArrayLength(chunkObj); 104 void* storage = alloca(chunkSize); 105 env->GetByteArrayRegion(chunkObj, 0, chunkSize, 106 reinterpret_cast<jbyte*>(storage)); 107 if (!env->ExceptionCheck()) { 108 // need to deserialize the chunk 109 Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage); 110 assert(chunkSize == chunk->serializedSize()); 111 // this relies on deserialization being done in place 112 Res_png_9patch::deserialize(chunk); 113 SkRegion* region = NULL; 114 NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion); 115 return (jint)region; 116 } 117 return 0; 118 } 119 120}; 121 122///////////////////////////////////////////////////////////////////////////////////////// 123 124#include <android_runtime/AndroidRuntime.h> 125 126static JNINativeMethod gNinePatchMethods[] = { 127 { "isNinePatchChunk", "([B)Z", (void*)SkNinePatchGlue::isNinePatchChunk }, 128 { "validateNinePatchChunk", "(I[B)V", (void*)SkNinePatchGlue::validateNinePatchChunk }, 129 { "nativeDraw", "(ILandroid/graphics/RectF;I[BI)V", (void*)SkNinePatchGlue::drawF }, 130 { "nativeDraw", "(ILandroid/graphics/Rect;I[BI)V", (void*)SkNinePatchGlue::drawI }, 131 { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I", 132 (void*)SkNinePatchGlue::getTransparentRegion } 133}; 134 135int register_android_graphics_NinePatch(JNIEnv* env); 136int register_android_graphics_NinePatch(JNIEnv* env) 137{ 138 return android::AndroidRuntime::registerNativeMethods(env, 139 "android/graphics/NinePatch", 140 gNinePatchMethods, 141 SK_ARRAY_COUNT(gNinePatchMethods)); 142} 143