Fix compilation errors for Android run

This commit is contained in:
Victor Shcherb 2012-05-04 16:24:21 +02:00
parent 537d80a27f
commit b57ef8b0b5
11 changed files with 317 additions and 273 deletions

View file

@ -1,4 +1,3 @@
ANDROID_BUILD := true
OSMAND_MAKEFILES := $(all-subdir-makefiles) OSMAND_MAKEFILES := $(all-subdir-makefiles)
# By default, include makefiles only once # By default, include makefiles only once

View file

@ -13,6 +13,7 @@ endif
LOCAL_CFLAGS := \ LOCAL_CFLAGS := \
-DGOOGLE_PROTOBUF_NO_RTTI \ -DGOOGLE_PROTOBUF_NO_RTTI \
-DANDROID_BUILD \
-DSK_BUILD_FOR_ANDROID \ -DSK_BUILD_FOR_ANDROID \
-DSK_BUILD_FOR_ANDROID_NDK \ -DSK_BUILD_FOR_ANDROID_NDK \
-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0 \ -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0 \

View file

@ -2,7 +2,6 @@
#include <vector> #include <vector>
#include <SkPath.h> #include <SkPath.h>
#include <SkBitmap.h> #include <SkBitmap.h>
#include <SkImageDecoder.h>
#include <jni.h> #include <jni.h>
#include <time.h> #include <time.h>
#include <math.h> #include <math.h>
@ -12,198 +11,6 @@
#include "osmand_log.h" #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) TextDrawInfo::TextDrawInfo(std::string itext)
: text(itext) : text(itext)
@ -225,8 +32,6 @@ IconDrawInfo::IconDrawInfo()
} }
RenderingContext::RenderingContext() RenderingContext::RenderingContext()
: javaRenderingContext(NULL)
, androidContext(NULL)
{ {
} }
@ -239,9 +44,11 @@ RenderingContext::~RenderingContext()
bool RenderingContext::interrupted() bool RenderingContext::interrupted()
{ {
return env->GetBooleanField(javaRenderingContext, jfield_RenderingContext_interrupted); return false;
} }
float getDensityValue(RenderingContext* rc, float val) float getDensityValue(RenderingContext* rc, float val)
{ {
if (rc->highResMode && rc->density > 1) if (rc->highResMode && rc->density > 1)
@ -296,10 +103,15 @@ int ElapsedTimer::getElapsedTime()
return elapsedTime / 1e6; return elapsedTime / 1e6;
} }
SkBitmap* RenderingContext::getCachedBitmap(const std::string& bitmapResource) {
return NULL;
}
HMAP::hash_map<std::string, SkBitmap*> cachedBitmaps; HMAP::hash_map<std::string, SkBitmap*> cachedBitmaps;
SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResource) SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResource)
{ {
JNIEnv* env = rc->env;
if(bitmapResource.size() == 0) if(bitmapResource.size() == 0)
return NULL; return NULL;
@ -309,43 +121,18 @@ SkBitmap* getCachedBitmap(RenderingContext* rc, const std::string& bitmapResourc
return itPreviouslyCachedBitmap->second; return itPreviouslyCachedBitmap->second;
rc->nativeOperations.pause(); rc->nativeOperations.pause();
SkBitmap* iconBitmap = rc->getCachedBitmap(bitmapResource);
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;
}
cachedBitmaps[bitmapResource] = iconBitmap; cachedBitmaps[bitmapResource] = iconBitmap;
rc->nativeOperations.start(); rc->nativeOperations.start();
env->ReleaseByteArrayElements(javaIconRawData, bitmapBuffer, JNI_ABORT);
env->DeleteLocalRef(javaIconRawData);
env->DeleteLocalRef(jstr);
return iconBitmap; return iconBitmap;
} }
std::string RenderingContext::getTranslatedString(const std::string& src) {
return src;
}
inline double getPowZoom(float zoom){ inline double getPowZoom(float zoom){
if(zoom >= 0 && zoom - floor(zoom) < 0.05f){ if(zoom >= 0 && zoom - floor(zoom) < 0.05f){
return 1 << ((int)zoom); return 1 << ((int)zoom);

View file

@ -1,7 +1,6 @@
#ifndef _OSMAND_COMMON_H #ifndef _OSMAND_COMMON_H
#define _OSMAND_COMMON_H #define _OSMAND_COMMON_H
#include <jni.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -83,19 +82,6 @@ using namespace std;
struct RenderingContext; 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 class ElapsedTimer
{ {
private: private:
@ -155,13 +141,11 @@ struct IconDrawInfo
struct RenderingContext struct RenderingContext
{ {
RenderingContext(); RenderingContext();
~RenderingContext(); virtual ~RenderingContext();
bool interrupted();
jobject javaRenderingContext; virtual bool interrupted();
virtual SkBitmap* getCachedBitmap(const std::string& bitmapResource);
jobject androidContext; virtual std::string getTranslatedString(const std::string& src);
JNIEnv* env;
bool useEnglishNames; bool useEnglishNames;
std::vector<TextDrawInfo*> textToDraw; std::vector<TextDrawInfo*> textToDraw;
@ -200,6 +184,7 @@ struct RenderingContext
// not expect any shadow // not expect any shadow
int shadowLevelMin; int shadowLevelMin;
int shadowLevelMax; int shadowLevelMax;
}; };
float getDensityValue(RenderingContext* rc, float val); float getDensityValue(RenderingContext* rc, float val);

View file

@ -0,0 +1,5 @@
#ifndef _JAVA_COMMON_WRAP_CPP
#define _JAVA_COMMON_WRAP_CPP
#endif

View file

@ -5,8 +5,29 @@
#include "java_wrap.h" #include "java_wrap.h"
#include "binaryRead.h" #include "binaryRead.h"
#include "rendering.h" #include "rendering.h"
#include <dlfcn.h>
#include <SkBitmap.h> #include <SkBitmap.h>
#include <SkCanvas.h> #include <SkCanvas.h>
#include <SkImageDecoder.h>
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, extern "C" JNIEXPORT void JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_deleteSearchResult(JNIEnv* ienv,
jobject obj, jint searchResult) { jobject obj, jint searchResult) {
@ -128,7 +149,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib
initObjects.start(); initObjects.start();
RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest); RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest);
RenderingContext rc; JNIRenderingContext rc;
pullFromJavaRenderingContext(ienv, renderingContext, &rc); pullFromJavaRenderingContext(ienv, renderingContext, &rc);
rc.useEnglishNames = useEnglishNames; rc.useEnglishNames = useEnglishNames;
ResultPublisher* result = ((ResultPublisher*) searchResult); ResultPublisher* result = ((ResultPublisher*) searchResult);
@ -214,7 +235,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib
initObjects.start(); initObjects.start();
RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest); RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest);
RenderingContext rc; JNIRenderingContext rc;
pullFromJavaRenderingContext(ienv, renderingContext, &rc); pullFromJavaRenderingContext(ienv, renderingContext, &rc);
rc.useEnglishNames = useEnglishNames; rc.useEnglishNames = useEnglishNames;
ResultPublisher* result = ((ResultPublisher*) searchResult); ResultPublisher* result = ((ResultPublisher*) searchResult);
@ -254,3 +275,166 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib
return resultObject; 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;
}

View file

@ -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 #endif

View file

@ -1,19 +1,23 @@
#ifndef _OSMAND_LOG_CPP #ifndef _OSMAND_LOG_CPP
#define _OSMAND_LOG_CPP #define _OSMAND_LOG_CPP
#include "osmand_log.h"
#ifdef ANDROID_BUILD #ifdef ANDROID_BUILD
#include <android/log.h> #include <android/log.h>
const char* const LOG_TAG = "net.osmand:native"; 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) { 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) { } 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 { } else {
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, msg); __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, msg, args);
} }
va_end(args);
} }

View file

@ -43,6 +43,16 @@ jfieldID RenderingRuleSearchRequest_fvalues;
jfieldID RenderingRuleSearchRequest_savedValues; jfieldID RenderingRuleSearchRequest_savedValues;
jfieldID RenderingRuleSearchRequest_savedFvalues; 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() { int RenderingRulesStorage::getPropertiesSize() {
return properties.size(); return properties.size();
} }

View file

@ -1,6 +1,5 @@
#include <jni.h>
#include "osmand_log.h" #include "osmand_log.h"
#include <dlfcn.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
@ -27,8 +26,6 @@
#include "textdraw.cpp" #include "textdraw.cpp"
#include "mapObjects.h" #include "mapObjects.h"
jclass jclass_JUnidecode;
jmethodID jmethod_JUnidecode_unidecode;
void calcPoint(std::pair<int, int> c, RenderingContext* rc) void calcPoint(std::pair<int, int> c, RenderingContext* rc)
{ {
@ -189,13 +186,7 @@ void renderText(MapDataObject* obj, RenderingRuleSearchRequest* req, RenderingCo
while (it != obj->objectNames.end()) { while (it != obj->objectNames.end()) {
if (it->second.length() > 0) { if (it->second.length() > 0) {
std::string name = it->second; std::string name = it->second;
if (rc->useEnglishNames) { name =rc->getTranslatedString(name);
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);
}
req->setInitialTagValueZoom(tag, value, rc->zoom, obj); req->setInitialTagValueZoom(tag, value, rc->zoom, obj);
req->setIntFilter(req->props()->R_TEXT_LENGTH, name.length()); req->setIntFilter(req->props()->R_TEXT_LENGTH, name.length());
std::string tagName = it->first == "name" ? "" : it->first; std::string tagName = it->first == "name" ? "" : it->first;
@ -602,9 +593,3 @@ void doRendering(std::vector <MapDataObject* > mapDataObjects, SkCanvas* canvas,
delete paint; delete paint;
rc->nativeOperations.pause(); 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;");
}

View file

@ -3,7 +3,6 @@
#include <algorithm> #include <algorithm>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <jni.h>
#include "SkTypes.h" #include "SkTypes.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "SkCanvas.h" #include "SkCanvas.h"