From c0c80f14afba322179ac505816cdc51267b3a6ce Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 31 Jul 2014 13:41:51 +0300 Subject: Android: Fix exceptions in ExtractStyle.java on Android L Android L adds support for 64 bit (arm and x86) and they did lots of changes that are incompatible with old implementation. Task-number: QTBUG-40120 Change-Id: I69b78a9eed896d2ddabc1bf2a55886faeae47974 Reviewed-by: J-P Nurmi --- src/3rdparty/android/extract.h | 53 ++++++++++++++++++ .../org/qtproject/qt5/android/ExtractStyle.java | 18 +++++-- src/plugins/platforms/android/extract.cpp | 62 +++++++++++++++++++++- 3 files changed, 128 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/3rdparty/android/extract.h b/src/3rdparty/android/extract.h index f7928e20a8..938ef9abfd 100644 --- a/src/3rdparty/android/extract.h +++ b/src/3rdparty/android/extract.h @@ -114,4 +114,57 @@ struct Res_png_9patch static Res_png_9patch* deserialize(const void* data); }; +struct Res_png_9patch20 +{ + Res_png_9patch20() : wasDeserialized(false), numXDivs(0), numYDivs(0), numColors(0), xDivsOffset(0), + yDivsOffset(0),paddingLeft(0), paddingRight(0), paddingTop(0), paddingBottom(0), + colorsOffset(0) { } + + int8_t wasDeserialized; + int8_t numXDivs; + int8_t numYDivs; + int8_t numColors; + + // The offset (from the start of this structure) to the xDivs & yDivs + // array for this 9patch. To get a pointer to this array, call + // getXDivs or getYDivs. Note that the serialized form for 9patches places + // the xDivs, yDivs and colors arrays immediately after the location + // of the Res_png_9patch struct. + uint32_t xDivsOffset; + uint32_t yDivsOffset; + + 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 + }; + + // The offset (from the start of this structure) to the colors array + // for this 9patch. + uint32_t colorsOffset; + + // Deserialize/Unmarshall the patch data + static Res_png_9patch20* deserialize(void* data); + + // 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. + inline int32_t* getXDivs() const { + return reinterpret_cast(reinterpret_cast(this) + xDivsOffset); + } + inline int32_t* getYDivs() const { + return reinterpret_cast(reinterpret_cast(this) + yDivsOffset); + } + inline uint32_t* getColors() const { + return reinterpret_cast(reinterpret_cast(this) + colorsOffset); + } + +} __attribute__((packed)); + #endif diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java index cc7fc505ee..4bd78bfe6a 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java +++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java @@ -90,6 +90,9 @@ public class ExtractStyle { native static int[] extractChunkInfo(byte[] chunkData); native static int[] extractNativeChunkInfo(int nativeChunk); + native static int[] extractChunkInfo20(byte[] chunkData); + native static int[] extractNativeChunkInfo20(long nativeChunk); + Class styleableClass = getStylableClass(); final int[] EMPTY_STATE_SET = {}; @@ -337,7 +340,10 @@ public class ExtractStyle { } public void drawPatch(Bitmap bmp, byte[] chunks, RectF dst, Paint paint) { - chunkData = extractChunkInfo(chunks); + if (Build.VERSION.SDK_INT > 19) + chunkData = extractChunkInfo20(chunks); + else + chunkData = extractChunkInfo(chunks); } } @@ -630,6 +636,8 @@ public class ExtractStyle { JSONObject stateJson = new JSONObject(); final Drawable d = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", Integer.TYPE).invoke(stateList, i); final int [] states = (int[]) StateListDrawable.class.getMethod("getStateSet", Integer.TYPE).invoke(stateList, i); + if (states == null) + continue; stateJson.put("states", getStatesList(states)); stateJson.put("drawable", getDrawable(d, filename+"__"+getStatesName(states))); array.put(stateJson); @@ -658,9 +666,7 @@ public class ExtractStyle { int [] intArray=(int[]) gradientStateClass.getField("mColors").get(obj); json.put("colors",getJsonArray(intArray, 0, intArray.length)); json.put("positions",getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj))); - json.put("solidColor",gradientStateClass.getField("mSolidColor").getInt(obj)); json.put("strokeWidth",gradientStateClass.getField("mStrokeWidth").getInt(obj)); - json.put("strokeColor",gradientStateClass.getField("mStrokeColor").getInt(obj)); json.put("strokeDashWidth",gradientStateClass.getField("mStrokeDashWidth").getFloat(obj)); json.put("strokeDashGap",gradientStateClass.getField("mStrokeDashGap").getFloat(obj)); json.put("radius",gradientStateClass.getField("mRadius").getFloat(obj)); @@ -676,6 +682,10 @@ public class ExtractStyle { json.put("thicknessRatio",gradientStateClass.getField("mThicknessRatio").getFloat(obj)); json.put("innerRadius",gradientStateClass.getField("mInnerRadius").getInt(obj)); json.put("thickness",gradientStateClass.getField("mThickness").getInt(obj)); + if (Build.VERSION.SDK_INT < 20) { + json.put("solidColor",gradientStateClass.getField("mSolidColor").getInt(obj)); + json.put("strokeColor",gradientStateClass.getField("mStrokeColor").getInt(obj)); + } } catch (Exception e) { e.printStackTrace(); } @@ -789,6 +799,8 @@ public class ExtractStyle { { Field mNativeChunk = np.getClass().getDeclaredField("mNativeChunk"); mNativeChunk.setAccessible(true); + if (Build.VERSION.SDK_INT > 19) + return getJsonChunkInfo(extractNativeChunkInfo20(mNativeChunk.getLong(np))); return getJsonChunkInfo(extractNativeChunkInfo(mNativeChunk.getInt(np))); } } diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp index 82687e61a7..25c3a1c29d 100644 --- a/src/plugins/platforms/android/extract.cpp +++ b/src/plugins/platforms/android/extract.cpp @@ -47,9 +47,7 @@ #include #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__) extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv * env, jobject, Res_png_9patch* chunk) { @@ -133,3 +131,63 @@ Res_png_9patch* Res_png_9patch::deserialize(const void* inData) deserializeInternal(inData, (Res_png_9patch*) inData); return (Res_png_9patch*) inData; } + +extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo20(JNIEnv * env, jobject, long addr) +{ + Res_png_9patch20* chunk = reinterpret_cast(addr); + Res_png_9patch20::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; + + int32_t* xDivs = chunk->getXDivs(); + int32_t* yDivs = chunk->getYDivs(); + uint32_t* colors = chunk->getColors(); + + for (int x = 0; x numXDivs; x ++) + data[pos++]=xDivs[x]; + for (int y = 0; y numYDivs; y ++) + data[pos++] = yDivs[y]; + for (int c = 0; c numColors; c ++) + data[pos++] = colors[c]; + env->SetIntArrayRegion(result, 0, size, data); + free(data); + return result; +} + +extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo20(JNIEnv * env, jobject obj, jbyteArray chunkObj) +{ + size_t chunkSize = env->GetArrayLength(chunkObj); + void* storage = alloca(chunkSize); + env->GetByteArrayRegion(chunkObj, 0, chunkSize, + reinterpret_cast(storage)); + + if (!env->ExceptionCheck()) + return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo20(env, obj, long(storage)); + else + env->ExceptionClear(); + return 0; +} + +static inline void fill9patchOffsets(Res_png_9patch20* patch) { + patch->xDivsOffset = sizeof(Res_png_9patch20); + patch->yDivsOffset = patch->xDivsOffset + (patch->numXDivs * sizeof(int32_t)); + patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t)); +} + +Res_png_9patch20* Res_png_9patch20::deserialize(void* inData) +{ + Res_png_9patch20* patch = reinterpret_cast(inData); + patch->wasDeserialized = true; + fill9patchOffsets(patch); + return patch; +} -- cgit v1.2.3