NinePatch.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(obj, 0); 25 if (array != NULL) 26 { 27 Res_png_9patch* chunk = (Res_png_9patch*)array; 28 int8_t numXDivs = chunk->numXDivs; 29 env->ReleasePrimitiveArrayCritical(obj, array, 0); 30 return array[0] != -1; 31 } 32 return false; 33 } 34 35 static void validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj) 36 { 37 if (env->GetArrayLength(obj) < (int) (sizeof(Res_png_9patch))) { 38 jniThrowException(env, "java/lang/RuntimeException", 39 "Array too small for chunk."); 40 return; 41 } 42 43 // XXX Also check that dimensions are correct. 44 } 45 46 static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, 47 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 48 { 49 jbyte* array = env->GetByteArrayElements(chunkObj, 0); 50 if (array != NULL) 51 { 52 size_t chunkSize = env->GetArrayLength(chunkObj); 53 void* deserializedArray = alloca(chunkSize); 54 Res_png_9patch* chunk = (Res_png_9patch*) deserializedArray; 55 assert(chunkSize == ((Res_png_9patch*) array)->serializedSize()); 56 memcpy(chunk, array, chunkSize); 57 Res_png_9patch::deserialize(chunk); 58 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL); 59 env->ReleaseByteArrayElements(chunkObj, array, 0); 60 } 61 } 62 63 static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF, 64 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 65 { 66 SkASSERT(canvas); 67 SkASSERT(boundsRectF); 68 SkASSERT(bitmap); 69 SkASSERT(chunkObj); 70 // paint is optional 71 72 SkRect bounds; 73 GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds); 74 75 draw(env, canvas, bounds, bitmap, chunkObj, paint); 76 } 77 78 static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect, 79 const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint) 80 { 81 SkASSERT(canvas); 82 SkASSERT(boundsRect); 83 SkASSERT(bitmap); 84 SkASSERT(chunkObj); 85 // paint is optional 86 87 SkRect bounds; 88 GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); 89 draw(env, canvas, bounds, bitmap, chunkObj, paint); 90 } 91 92 static jint getTransparentRegion(JNIEnv* env, jobject, 93 const SkBitmap* bitmap, jbyteArray chunkObj, 94 jobject boundsRect) 95 { 96 SkASSERT(bitmap); 97 SkASSERT(chunkObj); 98 SkASSERT(boundsRect); 99 100 SkRect bounds; 101 GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds); 102 jbyte* array = (jbyte*)env->GetByteArrayElements(chunkObj, 0); 103 if (array != NULL) 104 { 105 size_t chunkSize = env->GetArrayLength(chunkObj); 106 void* deserializedArray = alloca(chunkSize); 107 Res_png_9patch* chunk = (Res_png_9patch*) deserializedArray; 108 assert(chunkSize == ((Res_png_9patch*) array)->serializedSize()); 109 memcpy(chunk, array, chunkSize); 110 Res_png_9patch::deserialize(chunk); 111 SkRegion* region = NULL; 112 NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion); 113 env->ReleaseByteArrayElements(chunkObj, array, 0); 114 return (jint)region; 115 } 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