diff options
Diffstat (limited to 'Ministro/jni')
-rw-r--r-- | Ministro/jni/Android.mk | 10 | ||||
-rw-r--r-- | Ministro/jni/Application.mk | 1 | ||||
-rw-r--r-- | Ministro/jni/chmode.c | 27 | ||||
-rw-r--r-- | Ministro/jni/extract.cpp | 178 | ||||
-rw-r--r-- | Ministro/jni/extract.h | 101 |
5 files changed, 317 insertions, 0 deletions
diff --git a/Ministro/jni/Android.mk b/Ministro/jni/Android.mk new file mode 100644 index 0000000..93e8289 --- /dev/null +++ b/Ministro/jni/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := ministro +LOCAL_CFLAGS := -Werror +LOCAL_SRC_FILES := chmode.c extract.cpp +LOCAL_LDLIBS := -lm -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/Ministro/jni/Application.mk b/Ministro/jni/Application.mk new file mode 100644 index 0000000..a252a72 --- /dev/null +++ b/Ministro/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := all diff --git a/Ministro/jni/chmode.c b/Ministro/jni/chmode.c new file mode 100644 index 0000000..ed73182 --- /dev/null +++ b/Ministro/jni/chmode.c @@ -0,0 +1,27 @@ +/* + Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <jni.h> +#include <sys/stat.h> + +jint Java_org_kde_necessitas_ministro_MinistroActivity_nativeChmode(JNIEnv * env, jobject obj, jstring filePath, jint mode) +{ + const char *file = (*env)->GetStringUTFChars(env, filePath, 0); + int res = chmod(file, mode); + (*env)->ReleaseStringUTFChars(env, filePath, file); + return res; +} diff --git a/Ministro/jni/extract.cpp b/Ministro/jni/extract.cpp new file mode 100644 index 0000000..a125bfc --- /dev/null +++ b/Ministro/jni/extract.cpp @@ -0,0 +1,178 @@ +/* + Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <jni.h> +#include <android/log.h> +#include <extract.h> +#include <alloca.h> + +#define LOG_TAG "extractSyleInfo" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) +#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) + +const char * const NinePatchDrawableClassName = "android/graphics/drawable/NinePatchDrawable"; +const char * const NinePatchFieldIDName = "mNinePatch"; +static jfieldID m_ninePatchFieldID=0; + +const char * const NinePatchClassName = "android/graphics/NinePatch"; +const char * const ChunkFieldIDName = "mChunk"; +static jfieldID m_chunkFieldID=0; + +const char * const ClipStateClassName = "android/graphics/drawable/ClipDrawable$ClipState"; +const char * const ClipStateDrawableFieldIDName = "mDrawable"; +static jfieldID m_clipStateDrawableFieldID=0; + +bool setup(JNIEnv * env, jobject /*obj*/) +{ + jclass ninePatchClass = env->FindClass(NinePatchClassName); + if (!ninePatchClass) + { + LOGF("Unable to find class '%s'", NinePatchClassName); + return JNI_FALSE; + } + + m_chunkFieldID = env->GetFieldID(ninePatchClass, ChunkFieldIDName, "[B"); + if(!m_chunkFieldID) + { + LOGF("Unable to find field '%s'", ChunkFieldIDName); + return JNI_FALSE; + } + + jclass ninePatchDrawableClass = env->FindClass(NinePatchDrawableClassName); + if (!ninePatchDrawableClass) + { + LOGF("Unable to find class '%s'", NinePatchDrawableClassName); + return JNI_FALSE; + } + + m_ninePatchFieldID = env->GetFieldID(ninePatchDrawableClass, NinePatchFieldIDName, "Landroid/graphics/NinePatch;"); + if(!m_ninePatchFieldID) + { + LOGF("Unable to find field '%s'", NinePatchFieldIDName); + return JNI_FALSE; + } + + jclass clipStateDrawableClass = env->FindClass(ClipStateClassName); + if (!clipStateDrawableClass) + { + LOGF("Unable to find class '%s'", ClipStateClassName); + return JNI_FALSE; + } + + m_clipStateDrawableFieldID = env->GetFieldID(clipStateDrawableClass, ClipStateDrawableFieldIDName, "Landroid/graphics/drawable/Drawable;"); + if(!m_ninePatchFieldID) + { + LOGF("Unable to find field '%s'", NinePatchFieldIDName); + return JNI_FALSE; + } + + return JNI_TRUE; +} + +static void printChunkInformation(Res_png_9patch* chunk) +{ + LOGI("printChunkInformation x:%d , y:%d",chunk->numXDivs, chunk->numYDivs); + for (int x = 0; x < chunk->numXDivs; x ++) + LOGI("X CHUNK %d %d", x, chunk->xDivs[x]); + for (int y = 0; y < chunk->numYDivs; y ++) + LOGI("Y CHUNK %d %d", y, chunk->yDivs[y]); + LOGI("----"); +} + +extern "C" JNIEXPORT jintArray JNICALL Java_org_kde_necessitas_ministro_ExtractStyle_extractChunkInfo(JNIEnv * env, jobject obj, jbyteArray chunkObj) +{ + size_t chunkSize = env->GetArrayLength(chunkObj); + void* storage = alloca(chunkSize); + env->GetByteArrayRegion(chunkObj, 0, chunkSize, + reinterpret_cast<jbyte*>(storage)); + + if (!env->ExceptionCheck()) + { + // need to deserialize the chunk + Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage); + Res_png_9patch::deserialize(chunk); +// printChunkInformation(chunk); + jintArray result; + size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors; + result = env->NewIntArray(size); + if (!result) + return 0; + + jint *data = (jint*)malloc(sizeof(jint)*size); + size_t pos = 0; + data[pos++]=chunk->numXDivs; + data[pos++]=chunk->numYDivs; + data[pos++]=chunk->numColors; + for (int x = 0; x <chunk->numXDivs; x ++) + data[pos++]=chunk->xDivs[x]; + for (int y = 0; y <chunk->numYDivs; y ++) + data[pos++]=chunk->yDivs[y]; + for (int c = 0; c <chunk->numColors; c ++) + data[pos++]=chunk->colors[c]; + env->SetIntArrayRegion(result, 0, size, data); + free(data); + return result; + } + return 0; +} + +extern "C" JNIEXPORT jintArray JNICALL Java_org_kde_necessitas_ministro_ExtractStyle_extract9PatchInfo(JNIEnv * env, jobject obj, jobject ninePatchObject) +{ + if (!m_ninePatchFieldID || !m_chunkFieldID) + if (!setup(env, obj)) + return 0; + return Java_org_kde_necessitas_ministro_ExtractStyle_extractChunkInfo(env, obj + ,reinterpret_cast<jbyteArray>(env->GetObjectField( + env->GetObjectField(ninePatchObject, m_ninePatchFieldID) + , m_chunkFieldID)) ); +} + +extern "C" JNIEXPORT jobject JNICALL Java_org_kde_necessitas_ministro_ExtractStyle_getClipStateDrawableObject(JNIEnv * env, jobject obj, jobject clipStateObject) +{ + if (!m_ninePatchFieldID || !m_chunkFieldID || !m_clipStateDrawableFieldID) + if (!setup(env, obj)) + return 0; + return env->GetObjectField(clipStateObject, m_clipStateDrawableFieldID); +} + +// The following part was shamelessly stolen from ResourceTypes.cpp Android's sources +static void deserializeInternal(const void* inData, Res_png_9patch* outData) { + char* patch = (char*) inData; + if (inData != outData) { + memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors + memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors + } + outData->wasDeserialized = true; + char* data = (char*)outData; + data += sizeof(Res_png_9patch); + outData->xDivs = (int32_t*) data; + data += outData->numXDivs * sizeof(int32_t); + outData->yDivs = (int32_t*) data; + data += outData->numYDivs * sizeof(int32_t); + outData->colors = (uint32_t*) data; +} + +Res_png_9patch* Res_png_9patch::deserialize(const void* inData) +{ + if (sizeof(void*) != sizeof(int32_t)) { + LOGE("Cannot deserialize on non 32-bit system\n"); + return NULL; + } + deserializeInternal(inData, (Res_png_9patch*) inData); + return (Res_png_9patch*) inData; +} diff --git a/Ministro/jni/extract.h b/Ministro/jni/extract.h new file mode 100644 index 0000000..498ba7a --- /dev/null +++ b/Ministro/jni/extract.h @@ -0,0 +1,101 @@ +#ifndef EXTRACT_H +#define EXTRACT_H + +#include <cstdint> +#include <cstring> +// shamelessly stolen from ResourceTypes.h Android's sources +/** + * This chunk specifies how to split an image into segments for + * scaling. + * + * There are J horizontal and K vertical segments. These segments divide + * the image into J*K regions as follows (where J=4 and K=3): + * + * F0 S0 F1 S1 + * +-----+----+------+-------+ + * S2| 0 | 1 | 2 | 3 | + * +-----+----+------+-------+ + * | | | | | + * | | | | | + * F2| 4 | 5 | 6 | 7 | + * | | | | | + * | | | | | + * +-----+----+------+-------+ + * S3| 8 | 9 | 10 | 11 | + * +-----+----+------+-------+ + * + * Each horizontal and vertical segment is considered to by either + * stretchable (marked by the Sx labels) or fixed (marked by the Fy + * labels), in the horizontal or vertical axis, respectively. In the + * above example, the first is horizontal segment (F0) is fixed, the + * next is stretchable and then they continue to alternate. Note that + * the segment list for each axis can begin or end with a stretchable + * or fixed segment. + * + * The relative sizes of the stretchy segments indicates the relative + * amount of stretchiness of the regions bordered by the segments. For + * example, regions 3, 7 and 11 above will take up more horizontal space + * than regions 1, 5 and 9 since the horizontal segment associated with + * the first set of regions is larger than the other set of regions. The + * ratios of the amount of horizontal (or vertical) space taken by any + * two stretchable slices is exactly the ratio of their corresponding + * segment lengths. + * + * xDivs and yDivs point to arrays of horizontal and vertical pixel + * indices. The first pair of Divs (in either array) indicate the + * starting and ending points of the first stretchable segment in that + * axis. The next pair specifies the next stretchable segment, etc. So + * in the above example xDiv[0] and xDiv[1] specify the horizontal + * coordinates for the regions labeled 1, 5 and 9. xDiv[2] and + * xDiv[3] specify the coordinates for regions 3, 7 and 11. Note that + * the leftmost slices always start at x=0 and the rightmost slices + * always end at the end of the image. So, for example, the regions 0, + * 4 and 8 (which are fixed along the X axis) start at x value 0 and + * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at + * xDiv[2]. + * + * The array pointed to by the colors field lists contains hints for + * each of the regions. They are ordered according left-to-right and + * top-to-bottom as indicated above. For each segment that is a solid + * color the array entry will contain that color value; otherwise it + * will contain NO_COLOR. Segments that are completely transparent + * will always have the value TRANSPARENT_COLOR. + * + * The PNG chunk type is "npTc". + */ +struct Res_png_9patch +{ + Res_png_9patch() : wasDeserialized(false), xDivs(NULL), + yDivs(NULL), colors(NULL) { } + + int8_t wasDeserialized; + int8_t numXDivs; + int8_t numYDivs; + int8_t numColors; + + // These tell where the next section of a patch starts. + // For example, the first patch includes the pixels from + // 0 to xDivs[0]-1 and the second patch includes the pixels + // from xDivs[0] to xDivs[1]-1. + // Note: allocation/free of these pointers is left to the caller. + int32_t* xDivs; + int32_t* yDivs; + + int32_t paddingLeft, paddingRight; + int32_t paddingTop, paddingBottom; + + enum { + // The 9 patch segment is not a solid color. + NO_COLOR = 0x00000001, + + // The 9 patch segment is completely transparent. + TRANSPARENT_COLOR = 0x00000000 + }; + // Note: allocation/free of this pointer is left to the caller. + uint32_t* colors; + + // Deserialize/Unmarshall the patch data + static Res_png_9patch* deserialize(const void* data); +}; + +#endif |