diff --git a/Osmand-kernel/Android.mk b/Osmand-kernel/Android.mk index a201197c30..443df1dc1d 100755 --- a/Osmand-kernel/Android.mk +++ b/Osmand-kernel/Android.mk @@ -1,4 +1,3 @@ -ANDROID_BUILD := true OSMAND_MAKEFILES := $(all-subdir-makefiles) # By default, include makefiles only once diff --git a/Osmand-kernel/osmand/Android.mk b/Osmand-kernel/osmand/Android.mk index 96db692d84..26209e3b5f 100644 --- a/Osmand-kernel/osmand/Android.mk +++ b/Osmand-kernel/osmand/Android.mk @@ -13,6 +13,7 @@ endif LOCAL_CFLAGS := \ -DGOOGLE_PROTOBUF_NO_RTTI \ + -DANDROID_BUILD \ -DSK_BUILD_FOR_ANDROID \ -DSK_BUILD_FOR_ANDROID_NDK \ -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0 \ diff --git a/Osmand-kernel/osmand/src/common.cpp b/Osmand-kernel/osmand/src/common.cpp index 8db3a359c7..181e6ca015 100644 --- a/Osmand-kernel/osmand/src/common.cpp +++ b/Osmand-kernel/osmand/src/common.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -12,198 +11,6 @@ #include "osmand_log.h" -JavaVM* globalJVM = NULL; -// Forward declarations -void loadJniCommon(JNIEnv* env); -void loadJniRendering(JNIEnv* env); -void loadJniRenderingRules(JNIEnv* env); - -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) -{ - JNIEnv* globalJniEnv; - if(vm->GetEnv((void **)&globalJniEnv, JNI_VERSION_1_6)) - return JNI_ERR; /* JNI version not supported */ - globalJVM = vm; - - loadJniCommon(globalJniEnv); - loadJniRendering(globalJniEnv); - loadJniRenderingRules(globalJniEnv); - osmand_log_print(LOG_INFO, "JNI_OnLoad completed"); - - return JNI_VERSION_1_6; -} - -void throwNewException(JNIEnv* env, const char* msg) -{ - osmand_log_print(LOG_ERROR, msg); - env->ThrowNew(env->FindClass("java/lang/Exception"), msg); -} - -jclass findClass(JNIEnv* env, const char* className, bool mustHave/* = true*/) -{ - jclass javaClass = env->FindClass(className); - if(!javaClass && mustHave) - throwNewException(env, (std::string("Failed to find class ") + className).c_str()); - return (jclass)newGlobalRef(env, javaClass); -} - -jobject newGlobalRef(JNIEnv* env, jobject o) -{ - return env->NewGlobalRef(o); -} - -jfieldID getFid(JNIEnv* env, jclass cls, const char* fieldName, const char* sig) -{ - jfieldID jfield = env->GetFieldID(cls, fieldName, sig); - if(!jfield) - throwNewException(env, (std::string("Failed to find field ") + fieldName + std::string(" with signature ") + sig).c_str()); - return jfield; -} - -std::string getStringField(JNIEnv* env, jobject o, jfieldID fid) -{ - jstring jstr = (jstring)env->GetObjectField(o, fid); - if(!jstr) - { - throwNewException(env, "Failed to get object from field"); - return std::string(); - } - const char* utfBytes = env->GetStringUTFChars(jstr, NULL); - //TODO: I'm not quite sure that if real unicode will happen here, this will work as expected - std::string result(utfBytes); - env->ReleaseStringUTFChars(jstr, utfBytes); - env->DeleteLocalRef(jstr); - return result; -} - -std::string getString(JNIEnv* env, jstring jstr) -{ - if(!jstr) - { - throwNewException(env, "NULL jstring passed in"); - return std::string(); - } - const char* utfBytes = env->GetStringUTFChars(jstr, NULL); - //TODO: I'm not quite sure that if real unicode will happen here, this will work as expected - std::string result(utfBytes); - env->ReleaseStringUTFChars(jstr, utfBytes); - return result; -} - -std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid) -{ - return getString(env, (jstring)env->CallObjectMethod(o, fid)); -} - -std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid, int i) -{ - return getString(env, (jstring)env->CallObjectMethod(o, fid, i)); -} - -jclass jclass_RenderingContext = NULL; -jfieldID jfield_RenderingContext_interrupted = NULL; -jclass jclass_RenderingIcons = NULL; -jmethodID jmethod_RenderingIcons_getIconRawData = NULL; -jfieldID jfield_RenderingContext_leftX = NULL; -jfieldID jfield_RenderingContext_topY = NULL; -jfieldID jfield_RenderingContext_width = NULL; -jfieldID jfield_RenderingContext_height = NULL; -jfieldID jfield_RenderingContext_zoom = NULL; -jfieldID jfield_RenderingContext_rotate = NULL; -jfieldID jfield_RenderingContext_tileDivisor = NULL; -jfieldID jfield_RenderingContext_pointCount = NULL; -jfieldID jfield_RenderingContext_pointInsideCount = NULL; -jfieldID jfield_RenderingContext_visible = NULL; -jfieldID jfield_RenderingContext_allObjects = NULL; -jfieldID jfield_RenderingContext_cosRotateTileSize = NULL; -jfieldID jfield_RenderingContext_sinRotateTileSize = NULL; -jfieldID jfield_RenderingContext_density = NULL; -jfieldID jfield_RenderingContext_highResMode = NULL; -jfieldID jfield_RenderingContext_mapTextSize = NULL; -jfieldID jfield_RenderingContext_shadowRenderingMode = NULL; -jfieldID jfield_RenderingContext_shadowLevelMin = NULL; -jfieldID jfield_RenderingContext_shadowLevelMax = NULL; -jfieldID jfield_RenderingContext_ctx = NULL; -jfieldID jfield_RenderingContext_textRenderingTime = NULL; -jfieldID jfield_RenderingContext_lastRenderedKey = NULL; - -void loadJniCommon(JNIEnv* env) -{ - jclass_RenderingContext = findClass(env, "net/osmand/plus/render/OsmandRenderer$RenderingContext"); - jfield_RenderingContext_interrupted = getFid(env, jclass_RenderingContext, "interrupted", "Z"); - jfield_RenderingContext_leftX = getFid(env, jclass_RenderingContext, "leftX", "F" ); - jfield_RenderingContext_topY = getFid(env, jclass_RenderingContext, "topY", "F" ); - jfield_RenderingContext_width = getFid(env, jclass_RenderingContext, "width", "I" ); - jfield_RenderingContext_height = getFid(env, jclass_RenderingContext, "height", "I" ); - jfield_RenderingContext_zoom = getFid(env, jclass_RenderingContext, "zoom", "I" ); - jfield_RenderingContext_rotate = getFid(env, jclass_RenderingContext, "rotate", "F" ); - jfield_RenderingContext_tileDivisor = getFid(env, jclass_RenderingContext, "tileDivisor", "F" ); - jfield_RenderingContext_pointCount = getFid(env, jclass_RenderingContext, "pointCount", "I" ); - jfield_RenderingContext_pointInsideCount = getFid(env, jclass_RenderingContext, "pointInsideCount", "I" ); - jfield_RenderingContext_visible = getFid(env, jclass_RenderingContext, "visible", "I" ); - jfield_RenderingContext_allObjects = getFid(env, jclass_RenderingContext, "allObjects", "I" ); - jfield_RenderingContext_cosRotateTileSize = getFid(env, jclass_RenderingContext, "cosRotateTileSize", "F" ); - jfield_RenderingContext_sinRotateTileSize = getFid(env, jclass_RenderingContext, "sinRotateTileSize", "F" ); - jfield_RenderingContext_density = getFid(env, jclass_RenderingContext, "density", "F" ); - jfield_RenderingContext_highResMode = getFid(env, jclass_RenderingContext, "highResMode", "Z" ); - jfield_RenderingContext_mapTextSize = getFid(env, jclass_RenderingContext, "mapTextSize", "F" ); - jfield_RenderingContext_shadowRenderingMode = getFid(env, jclass_RenderingContext, "shadowRenderingMode", "I" ); - jfield_RenderingContext_shadowLevelMin = getFid(env, jclass_RenderingContext, "shadowLevelMin", "I" ); - jfield_RenderingContext_shadowLevelMax = getFid(env, jclass_RenderingContext, "shadowLevelMax", "I" ); - jfield_RenderingContext_ctx = getFid(env, jclass_RenderingContext, "ctx", "Landroid/content/Context;" ); - jfield_RenderingContext_textRenderingTime = getFid(env, jclass_RenderingContext, "textRenderingTime", "I" ); - jfield_RenderingContext_lastRenderedKey = getFid(env, jclass_RenderingContext, "lastRenderedKey", "I" ); - - jclass_RenderingIcons = findClass(env, "net/osmand/plus/render/RenderingIcons"); - jmethod_RenderingIcons_getIconRawData = env->GetStaticMethodID(jclass_RenderingIcons, - "getIconRawData", - "(Landroid/content/Context;Ljava/lang/String;)[B"); -} - -void pullFromJavaRenderingContext(JNIEnv* env, jobject jrc, RenderingContext* rc) -{ - rc->env = env; - rc->leftX = env->GetFloatField( jrc, jfield_RenderingContext_leftX ); - rc->topY = env->GetFloatField( jrc, jfield_RenderingContext_topY ); - rc->width = env->GetIntField( jrc, jfield_RenderingContext_width ); - rc->height = env->GetIntField( jrc, jfield_RenderingContext_height ); - - rc->zoom = env->GetIntField( jrc, jfield_RenderingContext_zoom ); - rc->rotate = env->GetFloatField( jrc, jfield_RenderingContext_rotate ); - rc->tileDivisor = env->GetFloatField( jrc, jfield_RenderingContext_tileDivisor ); - - rc->pointCount = env->GetIntField( jrc, jfield_RenderingContext_pointCount ); - rc->pointInsideCount = env->GetIntField( jrc, jfield_RenderingContext_pointInsideCount ); - rc->visible = env->GetIntField( jrc, jfield_RenderingContext_visible ); - rc->allObjects = env->GetIntField( jrc, jfield_RenderingContext_allObjects ); - - rc->cosRotateTileSize = env->GetFloatField( jrc, jfield_RenderingContext_cosRotateTileSize ); - rc->sinRotateTileSize = env->GetFloatField( jrc, jfield_RenderingContext_sinRotateTileSize ); - rc->density = env->GetFloatField( jrc, jfield_RenderingContext_density ); - rc->highResMode = env->GetBooleanField( jrc, jfield_RenderingContext_highResMode ); - rc->mapTextSize = env->GetFloatField( jrc, jfield_RenderingContext_mapTextSize ); - - rc->shadowRenderingMode = env->GetIntField( jrc, jfield_RenderingContext_shadowRenderingMode ); - rc->shadowLevelMin = env->GetIntField( jrc, jfield_RenderingContext_shadowLevelMin ); - rc->shadowLevelMax = env->GetIntField( jrc, jfield_RenderingContext_shadowLevelMax ); - rc->androidContext = env->GetObjectField(jrc, jfield_RenderingContext_ctx ); - rc->lastRenderedKey = 0; - - rc->javaRenderingContext = jrc; -} - - -void pushToJavaRenderingContext(JNIEnv* env, jobject jrc, RenderingContext* rc) -{ - env->SetIntField( jrc, jfield_RenderingContext_pointCount, (jint) rc->pointCount); - env->SetIntField( jrc, jfield_RenderingContext_pointInsideCount, (jint)rc->pointInsideCount); - env->SetIntField( jrc, jfield_RenderingContext_visible, (jint)rc->visible); - env->SetIntField( jrc, jfield_RenderingContext_allObjects, rc->allObjects); - env->SetIntField( jrc, jfield_RenderingContext_textRenderingTime, rc->textRendering.getElapsedTime()); - env->SetIntField( jrc, jfield_RenderingContext_lastRenderedKey, rc->lastRenderedKey); - - env->DeleteLocalRef(rc->androidContext); -} TextDrawInfo::TextDrawInfo(std::string itext) : text(itext) @@ -225,8 +32,6 @@ IconDrawInfo::IconDrawInfo() } RenderingContext::RenderingContext() - : javaRenderingContext(NULL) - , androidContext(NULL) { } @@ -239,9 +44,11 @@ RenderingContext::~RenderingContext() bool RenderingContext::interrupted() { - return env->GetBooleanField(javaRenderingContext, jfield_RenderingContext_interrupted); + return false; } + + float getDensityValue(RenderingContext* rc, float val) { if (rc->highResMode && rc->density > 1) @@ -296,10 +103,15 @@ int ElapsedTimer::getElapsedTime() return elapsedTime / 1e6; } +SkBitmap* RenderingContext::getCachedBitmap(const std::string& bitmapResource) { + return NULL; +} + + HMAP::hash_map cachedBitmaps; SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResource) { - JNIEnv* env = rc->env; + if(bitmapResource.size() == 0) return NULL; @@ -309,43 +121,18 @@ SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResourc return itPreviouslyCachedBitmap->second; rc->nativeOperations.pause(); - - jstring jstr = env->NewStringUTF(bitmapResource.c_str()); - jbyteArray javaIconRawData = (jbyteArray)env->CallStaticObjectMethod(jclass_RenderingIcons, jmethod_RenderingIcons_getIconRawData, rc->androidContext, jstr); - if(!javaIconRawData) - return NULL; - - jbyte* bitmapBuffer = env->GetByteArrayElements(javaIconRawData, NULL); - jint bufferLen = env->GetArrayLength(javaIconRawData); - - // Decode bitmap - SkBitmap* iconBitmap = new SkBitmap(); - //TODO: JPEG is badly supported! At the moment it needs sdcard to be present (sic). Patch that - if(!SkImageDecoder::DecodeMemory(bitmapBuffer, bufferLen, iconBitmap)) - { - // Failed to decode - delete iconBitmap; - - rc->nativeOperations.start(); - env->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); - env->DeleteLocalRef(javaIconRawData); - env->DeleteLocalRef(jstr); - - throwNewException(env, (std::string("Failed to decode ") + bitmapResource).c_str()); - - return NULL; - } + SkBitmap* iconBitmap = rc->getCachedBitmap(bitmapResource); cachedBitmaps[bitmapResource] = iconBitmap; - rc->nativeOperations.start(); - env->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); - env->DeleteLocalRef(javaIconRawData); - env->DeleteLocalRef(jstr); - return iconBitmap; } +std::string RenderingContext::getTranslatedString(const std::string& src) { + return src; +} + + inline double getPowZoom(float zoom){ if(zoom >= 0 && zoom - floor(zoom) < 0.05f){ return 1 << ((int)zoom); diff --git a/Osmand-kernel/osmand/src/common.h b/Osmand-kernel/osmand/src/common.h index 08fcb54fab..0a0275bc4d 100644 --- a/Osmand-kernel/osmand/src/common.h +++ b/Osmand-kernel/osmand/src/common.h @@ -1,7 +1,6 @@ #ifndef _OSMAND_COMMON_H #define _OSMAND_COMMON_H -#include #include #include @@ -83,19 +82,6 @@ using namespace std; struct RenderingContext; -// JNI Helpers -void throwNewException(JNIEnv* env, const char* msg); -jclass findClass(JNIEnv* env, const char* className, bool mustHave = true); -std::string getString(JNIEnv* env, jstring st); -std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid, int i); -std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid); -std::string getStringField(JNIEnv* env, jobject o, jfieldID fid); -jobject newGlobalRef(JNIEnv* env, jobject o); -jfieldID getFid(JNIEnv* env, jclass cls, const char* fieldName, const char* sig); - -void pullFromJavaRenderingContext(JNIEnv* env, jobject jrc, RenderingContext* rc); -void pushToJavaRenderingContext(JNIEnv* env, jobject jrc, RenderingContext* rc); - class ElapsedTimer { private: @@ -155,13 +141,11 @@ struct IconDrawInfo struct RenderingContext { RenderingContext(); - ~RenderingContext(); - bool interrupted(); + virtual ~RenderingContext(); - jobject javaRenderingContext; - - jobject androidContext; - JNIEnv* env; + virtual bool interrupted(); + virtual SkBitmap* getCachedBitmap(const std::string& bitmapResource); + virtual std::string getTranslatedString(const std::string& src); bool useEnglishNames; std::vector textToDraw; @@ -200,6 +184,7 @@ struct RenderingContext // not expect any shadow int shadowLevelMin; int shadowLevelMax; + }; float getDensityValue(RenderingContext* rc, float val); diff --git a/Osmand-kernel/osmand/src/java_common_wrap.h b/Osmand-kernel/osmand/src/java_common_wrap.h new file mode 100644 index 0000000000..c475c9eb35 --- /dev/null +++ b/Osmand-kernel/osmand/src/java_common_wrap.h @@ -0,0 +1,5 @@ +#ifndef _JAVA_COMMON_WRAP_CPP +#define _JAVA_COMMON_WRAP_CPP + + +#endif diff --git a/Osmand-kernel/osmand/src/java_wrap.cpp b/Osmand-kernel/osmand/src/java_wrap.cpp index 19b7941c77..d1fa3b7c21 100644 --- a/Osmand-kernel/osmand/src/java_wrap.cpp +++ b/Osmand-kernel/osmand/src/java_wrap.cpp @@ -5,8 +5,29 @@ #include "java_wrap.h" #include "binaryRead.h" #include "rendering.h" +#include #include #include +#include + +JavaVM* globalJVM = NULL; +// Forward declarations +void loadJniCommon(JNIEnv* env); +void loadJniRenderingRules(JNIEnv* env); + +extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) +{ + JNIEnv* globalJniEnv; + if(vm->GetEnv((void **)&globalJniEnv, JNI_VERSION_1_6)) + return JNI_ERR; /* JNI version not supported */ + globalJVM = vm; + + loadJniCommon(globalJniEnv); + loadJniRenderingRules(globalJniEnv); + osmand_log_print(LOG_INFO, "JNI_OnLoad completed"); + + return JNI_VERSION_1_6; +} extern "C" JNIEXPORT void JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_deleteSearchResult(JNIEnv* ienv, jobject obj, jint searchResult) { @@ -128,7 +149,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib initObjects.start(); RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest); - RenderingContext rc; + JNIRenderingContext rc; pullFromJavaRenderingContext(ienv, renderingContext, &rc); rc.useEnglishNames = useEnglishNames; ResultPublisher* result = ((ResultPublisher*) searchResult); @@ -214,7 +235,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib initObjects.start(); RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest); - RenderingContext rc; + JNIRenderingContext rc; pullFromJavaRenderingContext(ienv, renderingContext, &rc); rc.useEnglishNames = useEnglishNames; ResultPublisher* result = ((ResultPublisher*) searchResult); @@ -254,3 +275,166 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib return resultObject; } + + +jclass jclass_JUnidecode; +jmethodID jmethod_JUnidecode_unidecode; +jclass jclass_RenderingContext = NULL; +jfieldID jfield_RenderingContext_interrupted = NULL; +jclass jclass_RenderingIcons = NULL; +jmethodID jmethod_RenderingIcons_getIconRawData = NULL; +jfieldID jfield_RenderingContext_leftX = NULL; +jfieldID jfield_RenderingContext_topY = NULL; +jfieldID jfield_RenderingContext_width = NULL; +jfieldID jfield_RenderingContext_height = NULL; +jfieldID jfield_RenderingContext_zoom = NULL; +jfieldID jfield_RenderingContext_rotate = NULL; +jfieldID jfield_RenderingContext_tileDivisor = NULL; +jfieldID jfield_RenderingContext_pointCount = NULL; +jfieldID jfield_RenderingContext_pointInsideCount = NULL; +jfieldID jfield_RenderingContext_visible = NULL; +jfieldID jfield_RenderingContext_allObjects = NULL; +jfieldID jfield_RenderingContext_cosRotateTileSize = NULL; +jfieldID jfield_RenderingContext_sinRotateTileSize = NULL; +jfieldID jfield_RenderingContext_density = NULL; +jfieldID jfield_RenderingContext_highResMode = NULL; +jfieldID jfield_RenderingContext_mapTextSize = NULL; +jfieldID jfield_RenderingContext_shadowRenderingMode = NULL; +jfieldID jfield_RenderingContext_shadowLevelMin = NULL; +jfieldID jfield_RenderingContext_shadowLevelMax = NULL; +jfieldID jfield_RenderingContext_ctx = NULL; +jfieldID jfield_RenderingContext_textRenderingTime = NULL; +jfieldID jfield_RenderingContext_lastRenderedKey = NULL; + +void loadJniCommon(JNIEnv* env) +{ + jclass_RenderingContext = findClass(env, "net/osmand/plus/render/OsmandRenderer$RenderingContext"); + jfield_RenderingContext_interrupted = getFid(env, jclass_RenderingContext, "interrupted", "Z"); + jfield_RenderingContext_leftX = getFid(env, jclass_RenderingContext, "leftX", "F" ); + jfield_RenderingContext_topY = getFid(env, jclass_RenderingContext, "topY", "F" ); + jfield_RenderingContext_width = getFid(env, jclass_RenderingContext, "width", "I" ); + jfield_RenderingContext_height = getFid(env, jclass_RenderingContext, "height", "I" ); + jfield_RenderingContext_zoom = getFid(env, jclass_RenderingContext, "zoom", "I" ); + jfield_RenderingContext_rotate = getFid(env, jclass_RenderingContext, "rotate", "F" ); + jfield_RenderingContext_tileDivisor = getFid(env, jclass_RenderingContext, "tileDivisor", "F" ); + jfield_RenderingContext_pointCount = getFid(env, jclass_RenderingContext, "pointCount", "I" ); + jfield_RenderingContext_pointInsideCount = getFid(env, jclass_RenderingContext, "pointInsideCount", "I" ); + jfield_RenderingContext_visible = getFid(env, jclass_RenderingContext, "visible", "I" ); + jfield_RenderingContext_allObjects = getFid(env, jclass_RenderingContext, "allObjects", "I" ); + jfield_RenderingContext_cosRotateTileSize = getFid(env, jclass_RenderingContext, "cosRotateTileSize", "F" ); + jfield_RenderingContext_sinRotateTileSize = getFid(env, jclass_RenderingContext, "sinRotateTileSize", "F" ); + jfield_RenderingContext_density = getFid(env, jclass_RenderingContext, "density", "F" ); + jfield_RenderingContext_highResMode = getFid(env, jclass_RenderingContext, "highResMode", "Z" ); + jfield_RenderingContext_mapTextSize = getFid(env, jclass_RenderingContext, "mapTextSize", "F" ); + jfield_RenderingContext_shadowRenderingMode = getFid(env, jclass_RenderingContext, "shadowRenderingMode", "I" ); + jfield_RenderingContext_shadowLevelMin = getFid(env, jclass_RenderingContext, "shadowLevelMin", "I" ); + jfield_RenderingContext_shadowLevelMax = getFid(env, jclass_RenderingContext, "shadowLevelMax", "I" ); + jfield_RenderingContext_ctx = getFid(env, jclass_RenderingContext, "ctx", "Landroid/content/Context;" ); + jfield_RenderingContext_textRenderingTime = getFid(env, jclass_RenderingContext, "textRenderingTime", "I" ); + jfield_RenderingContext_lastRenderedKey = getFid(env, jclass_RenderingContext, "lastRenderedKey", "I" ); + + jclass_RenderingIcons = findClass(env, "net/osmand/plus/render/RenderingIcons"); + jmethod_RenderingIcons_getIconRawData = env->GetStaticMethodID(jclass_RenderingIcons, + "getIconRawData", + "(Landroid/content/Context;Ljava/lang/String;)[B"); + + jclass_JUnidecode = findClass(env, "net/sf/junidecode/Junidecode"); + jmethod_JUnidecode_unidecode = env->GetStaticMethodID(jclass_JUnidecode, "unidecode", "(Ljava/lang/String;)Ljava/lang/String;"); +} + +void pullFromJavaRenderingContext(JNIEnv* env, jobject jrc, JNIRenderingContext* rc) +{ + rc->env = env; + rc->leftX = env->GetFloatField( jrc, jfield_RenderingContext_leftX ); + rc->topY = env->GetFloatField( jrc, jfield_RenderingContext_topY ); + rc->width = env->GetIntField( jrc, jfield_RenderingContext_width ); + rc->height = env->GetIntField( jrc, jfield_RenderingContext_height ); + + rc->zoom = env->GetIntField( jrc, jfield_RenderingContext_zoom ); + rc->rotate = env->GetFloatField( jrc, jfield_RenderingContext_rotate ); + rc->tileDivisor = env->GetFloatField( jrc, jfield_RenderingContext_tileDivisor ); + + rc->pointCount = env->GetIntField( jrc, jfield_RenderingContext_pointCount ); + rc->pointInsideCount = env->GetIntField( jrc, jfield_RenderingContext_pointInsideCount ); + rc->visible = env->GetIntField( jrc, jfield_RenderingContext_visible ); + rc->allObjects = env->GetIntField( jrc, jfield_RenderingContext_allObjects ); + + rc->cosRotateTileSize = env->GetFloatField( jrc, jfield_RenderingContext_cosRotateTileSize ); + rc->sinRotateTileSize = env->GetFloatField( jrc, jfield_RenderingContext_sinRotateTileSize ); + rc->density = env->GetFloatField( jrc, jfield_RenderingContext_density ); + rc->highResMode = env->GetBooleanField( jrc, jfield_RenderingContext_highResMode ); + rc->mapTextSize = env->GetFloatField( jrc, jfield_RenderingContext_mapTextSize ); + + rc->shadowRenderingMode = env->GetIntField( jrc, jfield_RenderingContext_shadowRenderingMode ); + rc->shadowLevelMin = env->GetIntField( jrc, jfield_RenderingContext_shadowLevelMin ); + rc->shadowLevelMax = env->GetIntField( jrc, jfield_RenderingContext_shadowLevelMax ); + rc->androidContext = env->GetObjectField(jrc, jfield_RenderingContext_ctx ); + rc->lastRenderedKey = 0; + + rc->javaRenderingContext = jrc; +} + + +void pushToJavaRenderingContext(JNIEnv* env, jobject jrc, JNIRenderingContext* rc) +{ + env->SetIntField( jrc, jfield_RenderingContext_pointCount, (jint) rc->pointCount); + env->SetIntField( jrc, jfield_RenderingContext_pointInsideCount, (jint)rc->pointInsideCount); + env->SetIntField( jrc, jfield_RenderingContext_visible, (jint)rc->visible); + env->SetIntField( jrc, jfield_RenderingContext_allObjects, rc->allObjects); + env->SetIntField( jrc, jfield_RenderingContext_textRenderingTime, rc->textRendering.getElapsedTime()); + env->SetIntField( jrc, jfield_RenderingContext_lastRenderedKey, rc->lastRenderedKey); + + env->DeleteLocalRef(rc->androidContext); +} + +bool JNIRenderingContext::interrupted() +{ + return env->GetBooleanField(javaRenderingContext, jfield_RenderingContext_interrupted); +} + +SkBitmap* JNIRenderingContext::getCachedBitmap(const std::string& bitmapResource) { + JNIEnv* env = this->env; + jstring jstr = env->NewStringUTF(bitmapResource.c_str()); + jbyteArray javaIconRawData = (jbyteArray)env->CallStaticObjectMethod(jclass_RenderingIcons, jmethod_RenderingIcons_getIconRawData, this->androidContext, jstr); + if(!javaIconRawData) + return NULL; + + jbyte* bitmapBuffer = env->GetByteArrayElements(javaIconRawData, NULL); + jint bufferLen = env->GetArrayLength(javaIconRawData); + + // Decode bitmap + SkBitmap* iconBitmap = new SkBitmap(); + //TODO: JPEG is badly supported! At the moment it needs sdcard to be present (sic). Patch that + if(!SkImageDecoder::DecodeMemory(bitmapBuffer, bufferLen, iconBitmap)) + { + // Failed to decode + delete iconBitmap; + + this->nativeOperations.start(); + env->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); + env->DeleteLocalRef(javaIconRawData); + env->DeleteLocalRef(jstr); + + throwNewException(env, (std::string("Failed to decode ") + bitmapResource).c_str()); + + return NULL; + } + + env->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT); + env->DeleteLocalRef(javaIconRawData); + env->DeleteLocalRef(jstr); + + return iconBitmap; +} + +std::string JNIRenderingContext::getTranslatedString(const std::string& name) { + if (this->useEnglishNames) { + jstring n = this->env->NewStringUTF(name.c_str()); + std::string res = getString(this->env, + (jstring) this->env->CallStaticObjectMethod(jclass_JUnidecode, jmethod_JUnidecode_unidecode, n)); + this->env->DeleteLocalRef(n); + return res; + } + return name; +} + diff --git a/Osmand-kernel/osmand/src/java_wrap.h b/Osmand-kernel/osmand/src/java_wrap.h index b65cf699ee..0bee0593a1 100644 --- a/Osmand-kernel/osmand/src/java_wrap.h +++ b/Osmand-kernel/osmand/src/java_wrap.h @@ -21,4 +21,89 @@ struct ResultJNIPublisher : ResultPublisher { } }; +struct JNIRenderingContext : RenderingContext +{ + jobject javaRenderingContext; + jobject androidContext; + JNIEnv* env; + JNIRenderingContext() : javaRenderingContext(NULL), androidContext(NULL) { + } + + virtual SkBitmap* getCachedBitmap(const std::string& bitmapResource); + virtual std::string getTranslatedString(const std::string& src); + virtual bool interrupted(); + virtual ~JNIRenderingContext(){} +}; + +void pullFromJavaRenderingContext(JNIEnv* env, jobject jrc, JNIRenderingContext* rc); +void pushToJavaRenderingContext(JNIEnv* env, jobject jrc, JNIRenderingContext* rc); + +jobject newGlobalRef(JNIEnv* env, jobject o) +{ + return env->NewGlobalRef(o); +} + +void throwNewException(JNIEnv* env, const char* msg) +{ + osmand_log_print(LOG_ERROR, msg); + env->ThrowNew(env->FindClass("java/lang/Exception"), msg); +} + +jclass findClass(JNIEnv* env, const char* className, bool mustHave = true) +{ + jclass javaClass = env->FindClass(className); + if(!javaClass && mustHave) + throwNewException(env, (std::string("Failed to find class ") + className).c_str()); + return (jclass)newGlobalRef(env, javaClass); +} + + +jfieldID getFid(JNIEnv* env, jclass cls, const char* fieldName, const char* sig) +{ + jfieldID jfield = env->GetFieldID(cls, fieldName, sig); + if(!jfield) + throwNewException(env, (std::string("Failed to find field ") + fieldName + std::string(" with signature ") + sig).c_str()); + return jfield; +} + +std::string getStringField(JNIEnv* env, jobject o, jfieldID fid) +{ + jstring jstr = (jstring)env->GetObjectField(o, fid); + if(!jstr) + { + throwNewException(env, "Failed to get object from field"); + return std::string(); + } + const char* utfBytes = env->GetStringUTFChars(jstr, NULL); + //TODO: I'm not quite sure that if real unicode will happen here, this will work as expected + std::string result(utfBytes); + env->ReleaseStringUTFChars(jstr, utfBytes); + env->DeleteLocalRef(jstr); + return result; +} + +std::string getString(JNIEnv* env, jstring jstr) +{ + if(!jstr) + { + throwNewException(env, "NULL jstring passed in"); + return std::string(); + } + const char* utfBytes = env->GetStringUTFChars(jstr, NULL); + //TODO: I'm not quite sure that if real unicode will happen here, this will work as expected + std::string result(utfBytes); + env->ReleaseStringUTFChars(jstr, utfBytes); + return result; +} + +std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid) +{ + return getString(env, (jstring)env->CallObjectMethod(o, fid)); +} + +std::string getStringMethod(JNIEnv* env, jobject o, jmethodID fid, int i) +{ + return getString(env, (jstring)env->CallObjectMethod(o, fid, i)); +} + #endif diff --git a/Osmand-kernel/osmand/src/osmand_log.cpp b/Osmand-kernel/osmand/src/osmand_log.cpp index 81c8f7699f..bd0fff85ad 100644 --- a/Osmand-kernel/osmand/src/osmand_log.cpp +++ b/Osmand-kernel/osmand/src/osmand_log.cpp @@ -1,19 +1,23 @@ #ifndef _OSMAND_LOG_CPP #define _OSMAND_LOG_CPP +#include "osmand_log.h" #ifdef ANDROID_BUILD #include const char* const LOG_TAG = "net.osmand:native"; -void osmand_log_print(int type, const char* msg) { +void osmand_log_print(int type, const char* msg, ...) { + va_list args; + va_start( args, msg); if(type == LOG_ERROR) { - __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, msg); + __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, msg, args); } else if(type == LOG_INFO) { - __android_log_print(ANDROID_LOG_INFO, LOG_TAG, msg); + __android_log_print(ANDROID_LOG_INFO, LOG_TAG, msg, args); } else { - __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, msg); + __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, msg, args); } + va_end(args); } diff --git a/Osmand-kernel/osmand/src/renderRules.cpp b/Osmand-kernel/osmand/src/renderRules.cpp index a0deb46ccd..57767217bd 100644 --- a/Osmand-kernel/osmand/src/renderRules.cpp +++ b/Osmand-kernel/osmand/src/renderRules.cpp @@ -43,6 +43,16 @@ jfieldID RenderingRuleSearchRequest_fvalues; jfieldID RenderingRuleSearchRequest_savedValues; jfieldID RenderingRuleSearchRequest_savedFvalues; +/// TODO Forward declaration +jobject newGlobalRef(JNIEnv* env, jobject o); +void throwNewException(JNIEnv* env, const char* msg); +jfieldID getFid(JNIEnv* env, jclass cls, const char* fieldName, const char* sig); +std::string getStringField(JNIEnv* env, jobject o, jfieldID fid); +jclass findClass(JNIEnv* env, const char* className, bool mustHave = true); + + + + int RenderingRulesStorage::getPropertiesSize() { return properties.size(); } diff --git a/Osmand-kernel/osmand/src/rendering.cpp b/Osmand-kernel/osmand/src/rendering.cpp index b4b8343ac9..3bb3aaec7d 100644 --- a/Osmand-kernel/osmand/src/rendering.cpp +++ b/Osmand-kernel/osmand/src/rendering.cpp @@ -1,6 +1,5 @@ -#include #include "osmand_log.h" -#include + #include #include @@ -27,8 +26,6 @@ #include "textdraw.cpp" #include "mapObjects.h" -jclass jclass_JUnidecode; -jmethodID jmethod_JUnidecode_unidecode; void calcPoint(std::pair c, RenderingContext* rc) { @@ -189,13 +186,7 @@ void renderText(MapDataObject* obj, RenderingRuleSearchRequest* req, RenderingCo while (it != obj->objectNames.end()) { if (it->second.length() > 0) { std::string name = it->second; - if (rc->useEnglishNames) { - jstring n = rc->env->NewStringUTF(name.c_str()); - name = getString(rc->env, - (jstring) rc->env->CallStaticObjectMethod(jclass_JUnidecode, - jmethod_JUnidecode_unidecode, n)); - rc->env->DeleteLocalRef(n); - } + name =rc->getTranslatedString(name); req->setInitialTagValueZoom(tag, value, rc->zoom, obj); req->setIntFilter(req->props()->R_TEXT_LENGTH, name.length()); std::string tagName = it->first == "name" ? "" : it->first; @@ -602,9 +593,3 @@ void doRendering(std::vector mapDataObjects, SkCanvas* canvas, delete paint; rc->nativeOperations.pause(); } - -void loadJniRendering(JNIEnv* env) -{ - jclass_JUnidecode = findClass(env, "net/sf/junidecode/Junidecode"); - jmethod_JUnidecode_unidecode = env->GetStaticMethodID(jclass_JUnidecode, "unidecode", "(Ljava/lang/String;)Ljava/lang/String;"); -} diff --git a/Osmand-kernel/osmand/src/textdraw.cpp b/Osmand-kernel/osmand/src/textdraw.cpp index 2769efa743..1ca7373517 100644 --- a/Osmand-kernel/osmand/src/textdraw.cpp +++ b/Osmand-kernel/osmand/src/textdraw.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "SkTypes.h" #include "SkTypeface.h" #include "SkCanvas.h"