summaryrefslogtreecommitdiffstats
path: root/Ministro/jni
diff options
context:
space:
mode:
Diffstat (limited to 'Ministro/jni')
-rw-r--r--Ministro/jni/Android.mk10
-rw-r--r--Ministro/jni/Application.mk1
-rw-r--r--Ministro/jni/chmode.c27
-rw-r--r--Ministro/jni/extract.cpp178
-rw-r--r--Ministro/jni/extract.h101
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