From 14bbbb000a77399f89623fbd565b97e31fada214 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Sat, 3 Mar 2012 18:47:28 +0200 Subject: [PATCH] Fixed icon loading --- OsmAnd/jni/osmand/Android.mk | 20 +++++++++-- OsmAnd/jni/osmand/common.cpp | 33 ++++++++++++------- OsmAnd/jni/osmand/common.h | 2 +- OsmAnd/jni/osmand/rendering.cpp | 10 +++--- OsmAnd/jni/skia/Android.mk | 1 + .../osmand/plus/render/RenderingIcons.java | 32 +++++++++--------- 6 files changed, 59 insertions(+), 39 deletions(-) diff --git a/OsmAnd/jni/osmand/Android.mk b/OsmAnd/jni/osmand/Android.mk index 14d92bd5ea..58fdd951d3 100644 --- a/OsmAnd/jni/osmand/Android.mk +++ b/OsmAnd/jni/osmand/Android.mk @@ -54,11 +54,25 @@ LOCAL_CFLAGS += \ endif ifneq ($(LOCAL_ARM_NEON),true) -LOCAL_STATIC_LIBRARIES := proto skia +LOCAL_STATIC_LIBRARIES := \ + proto \ + libjpeg \ + libft2_static \ + libpng \ + libgif \ + libexpat_static +LOCAL_WHOLE_STATIC_LIBRARIES := skia else -LOCAL_STATIC_LIBRARIES := proto_neon skia_neon +LOCAL_STATIC_LIBRARIES := \ + proto_neon \ + libjpeg_neon \ + libft2_static_neon \ + libpng_neon \ + libgif_neon \ + libexpat_static_neon +LOCAL_WHOLE_STATIC_LIBRARIES := skia_neon endif -LOCAL_LDLIBS := -llog -ljnigraphics +LOCAL_LDLIBS := -lz -llog -ljnigraphics include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/OsmAnd/jni/osmand/common.cpp b/OsmAnd/jni/osmand/common.cpp index 96f1b3904f..535b0d4e76 100644 --- a/OsmAnd/jni/osmand/common.cpp +++ b/OsmAnd/jni/osmand/common.cpp @@ -120,7 +120,7 @@ std::string getStringMethod(jobject o, jmethodID fid, int i) jclass jclass_RenderingContext = NULL; jfieldID jfield_RenderingContext_interrupted = NULL; jclass jclass_RenderingIcons = NULL; -jmethodID jmethod_RenderingIcons_getIconAsByteBuffer = NULL; +jmethodID jmethod_RenderingIcons_getIconRawData = NULL; jfieldID jfield_RenderingContext_leftX = NULL; jfieldID jfield_RenderingContext_topY = NULL; jfieldID jfield_RenderingContext_width = NULL; @@ -172,9 +172,9 @@ void loadJniCommon() jfield_RenderingContext_lastRenderedKey = getFid( jclass_RenderingContext, "lastRenderedKey", "I" ); jclass_RenderingIcons = findClass("net/osmand/plus/render/RenderingIcons"); - jmethod_RenderingIcons_getIconAsByteBuffer = getGlobalJniEnv()->GetStaticMethodID(jclass_RenderingIcons, - "getIconAsByteBuffer", - "(Landroid/content/Context;Ljava/lang/String;)Ljava/nio/ByteBuffer;"); + jmethod_RenderingIcons_getIconRawData = getGlobalJniEnv()->GetStaticMethodID(jclass_RenderingIcons, + "getIconRawData", + "(Landroid/content/Context;Ljava/lang/String;)[B"); } //TODO: Dead code @@ -321,9 +321,11 @@ int ElapsedTimer::getElapsedTime() } std::hash_map cachedBitmaps; - -SkBitmap* getCachedBitmap(RenderingContext* rc, std::string bitmapResource) +SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResource) { + if(bitmapResource.size() == 0) + return NULL; + // Try to find previously cached std::hash_map::iterator itPreviouslyCachedBitmap = cachedBitmaps.find(bitmapResource); if (itPreviouslyCachedBitmap != cachedBitmaps.end()) @@ -331,15 +333,20 @@ SkBitmap* getCachedBitmap(RenderingContext* rc, std::string bitmapResource) rc->nativeOperations.pause(); + __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getCachedBitmap : %s", bitmapResource.c_str()); + jstring jstr = getGlobalJniEnv()->NewStringUTF(bitmapResource.c_str()); - jobject javaIconByteBuffer = getGlobalJniEnv()->CallStaticObjectMethod(jclass_RenderingIcons, jmethod_RenderingIcons_getIconAsByteBuffer, rc->androidContext, jstr); - if(!javaIconByteBuffer) + jbyteArray javaIconRawData = (jbyteArray)getGlobalJniEnv()->CallStaticObjectMethod(jclass_RenderingIcons, jmethod_RenderingIcons_getIconRawData, rc->androidContext, jstr); + if(!javaIconRawData) return NULL; + jbyte* bitmapBuffer = getGlobalJniEnv()->GetByteArrayElements(javaIconRawData, NULL); + size_t bufferLen = getGlobalJniEnv()->GetArrayLength(javaIconRawData); + + __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "getCachedBitmap : bitmap buffer len %d at %p", bufferLen, bitmapBuffer); + // Decode bitmap SkBitmap* iconBitmap = new SkBitmap(); - void* bitmapBuffer = getGlobalJniEnv()->GetDirectBufferAddress(javaIconByteBuffer); - size_t bufferLen = getGlobalJniEnv()->GetDirectBufferCapacity(javaIconByteBuffer); //TODO: JPEG is badly supported! At the moment it needs sdcard to be present (sic). Patch that if(!SkImageDecoder::DecodeMemory(bitmapBuffer, bufferLen, iconBitmap)) { @@ -347,7 +354,8 @@ SkBitmap* getCachedBitmap(RenderingContext* rc, std::string bitmapResource) delete iconBitmap; rc->nativeOperations.start(); - getGlobalJniEnv()->DeleteLocalRef(javaIconByteBuffer); + getGlobalJniEnv()->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); + getGlobalJniEnv()->DeleteLocalRef(javaIconRawData); getGlobalJniEnv()->DeleteLocalRef(jstr); throwNewException((std::string("Failed to decode ") + bitmapResource).c_str()); @@ -358,7 +366,8 @@ SkBitmap* getCachedBitmap(RenderingContext* rc, std::string bitmapResource) rc->nativeOperations.start(); - getGlobalJniEnv()->DeleteLocalRef(javaIconByteBuffer); + getGlobalJniEnv()->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); + getGlobalJniEnv()->DeleteLocalRef(javaIconRawData); getGlobalJniEnv()->DeleteLocalRef(jstr); return iconBitmap; diff --git a/OsmAnd/jni/osmand/common.h b/OsmAnd/jni/osmand/common.h index d3783d9110..739d165fac 100644 --- a/OsmAnd/jni/osmand/common.h +++ b/OsmAnd/jni/osmand/common.h @@ -143,6 +143,6 @@ struct RenderingContext float getDensityValue(RenderingContext* rc, float val); -SkBitmap* getCachedBitmap(RenderingContext* rc, std::string bitmapResource); +SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResource); #endif /*_OSMAND_COMMON_H*/ diff --git a/OsmAnd/jni/osmand/rendering.cpp b/OsmAnd/jni/osmand/rendering.cpp index cf1a987f4e..abf33fb2f9 100644 --- a/OsmAnd/jni/osmand/rendering.cpp +++ b/OsmAnd/jni/osmand/rendering.cpp @@ -493,14 +493,12 @@ void drawPoint(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas* c std::string resId = req->getStringPropertyValue(req-> props()-> R_ICON); SkBitmap* bmp = getCachedBitmap(rc, resId); std::string name; - if (renderText) { + if (renderText) name = mObj->name; - } - if (!bmp && name.length() == 0) { + + if (!bmp && name.length() == 0) return; - } - - + jint length = mObj->points.size(); rc->visible++; float px = 0; diff --git a/OsmAnd/jni/skia/Android.mk b/OsmAnd/jni/skia/Android.mk index a1dbd37cbc..5561f3e358 100755 --- a/OsmAnd/jni/skia/Android.mk +++ b/OsmAnd/jni/skia/Android.mk @@ -200,6 +200,7 @@ LOCAL_SRC_FILES := \ $(OSMAND_SKIA_LOC)/src/images/SkImageRef.cpp \ $(OSMAND_SKIA_LOC)/src/images/SkImageRefPool.cpp \ $(OSMAND_SKIA_LOC)/src/images/SkImageRef_GlobalPool.cpp \ + $(OSMAND_SKIA_LOC)/src/images/SkJpegUtility.cpp \ $(OSMAND_SKIA_LOC)/src/images/SkMovie.cpp \ $(OSMAND_SKIA_LOC)/src/images/SkMovie_gif.cpp \ $(OSMAND_SKIA_LOC)/src/images/SkPageFlipper.cpp \ diff --git a/OsmAnd/src/net/osmand/plus/render/RenderingIcons.java b/OsmAnd/src/net/osmand/plus/render/RenderingIcons.java index b9a6019b46..feba2a04ae 100644 --- a/OsmAnd/src/net/osmand/plus/render/RenderingIcons.java +++ b/OsmAnd/src/net/osmand/plus/render/RenderingIcons.java @@ -5,6 +5,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.nio.ByteBuffer; import java.io.InputStream; +import java.io.ByteArrayOutputStream; import org.apache.commons.logging.Log; @@ -29,7 +30,7 @@ public class RenderingIcons { return icons.containsKey(s); } - public static ByteBuffer getIconAsByteBuffer(Context ctx, String s) { + public static byte[] getIconRawData(Context ctx, String s) { Integer resId = icons.get(s); // Quite bad error @@ -37,23 +38,20 @@ public class RenderingIcons { return null; try { - final AssetFileDescriptor iconAssetFd = ctx.getResources().openRawResourceFd(resId.intValue()); - if(iconAssetFd == null) - return null; - - final long iconAssetLen = iconAssetFd.getLength(); - final ByteBuffer iconByteBuffer = ByteBuffer.allocate((int)iconAssetLen); - final InputStream inputStream = iconAssetFd.createInputStream(); - if(inputStream == null) - return null; - - long consumedBytes = 0; - while(consumedBytes < iconAssetLen) { - consumedBytes += inputStream.read(iconByteBuffer.array(), (int)(iconByteBuffer.arrayOffset() + consumedBytes), (int)(iconAssetLen - consumedBytes)); + final InputStream inputStream = ctx.getResources().openRawResource(resId.intValue()); + final ByteArrayOutputStream proxyOutputStream = new ByteArrayOutputStream(1024); + final byte[] ioBuffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(ioBuffer)) >= 0) { + proxyOutputStream.write(ioBuffer, 0, bytesRead); } - - iconAssetFd.close(); - return iconByteBuffer; + inputStream.close(); + final byte[] bitmapData = proxyOutputStream.toByteArray(); + log.info("Icon data length is " + bitmapData.length); //$NON-NLS-1$ + + //if(android.graphics.BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length) == null) + // throw new Exception(); + return bitmapData; } catch(Throwable e) { log.error("Failed to get byte stream from icon", e); //$NON-NLS-1$ return null;