2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
#include <jni.h>
|
|
|
|
#include <android/log.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2011-10-23 16:47:28 +02:00
|
|
|
#include "SkTypes.h"
|
|
|
|
#include "SkBitmap.h"
|
2011-10-23 18:09:35 +02:00
|
|
|
#include "SkShader.h"
|
|
|
|
#include "SkBitmapProcShader.h"
|
|
|
|
#include "SkPathEffect.h"
|
|
|
|
#include "SkBlurDrawLooper.h"
|
|
|
|
#include "SkDashPathEffect.h"
|
2011-10-23 16:47:28 +02:00
|
|
|
#include "SkCanvas.h"
|
|
|
|
#include "SkPaint.h"
|
|
|
|
#include "SkPath.h"
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
JNIEnv* env;
|
|
|
|
jclass MultiPolygonClass;
|
|
|
|
|
|
|
|
jclass PathClass;
|
|
|
|
jmethodID Path_init;
|
|
|
|
jmethodID Path_moveTo;
|
|
|
|
jmethodID Path_lineTo;
|
|
|
|
|
|
|
|
jclass CanvasClass;
|
|
|
|
jmethodID Canvas_drawPath;
|
2011-10-22 20:47:30 +02:00
|
|
|
jfieldID Canvas_nativeCanvas;
|
2011-10-22 14:00:59 +02:00
|
|
|
|
2011-10-23 18:41:49 +02:00
|
|
|
jclass RenderingIconsClass;
|
|
|
|
jmethodID RenderingIcons_getIcon;
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jclass RenderingRuleStoragePropertiesClass;
|
|
|
|
jclass RenderingRulePropertyClass;
|
|
|
|
|
|
|
|
jclass RenderingRuleSearchRequestClass;
|
|
|
|
jfieldID RenderingRuleSearchRequest_ALL;
|
|
|
|
jmethodID RenderingRuleSearchRequest_setInitialTagValueZoom;
|
|
|
|
jmethodID RenderingRuleSearchRequest_getIntPropertyValue;
|
|
|
|
jmethodID RenderingRuleSearchRequest_getFloatPropertyValue;
|
|
|
|
jmethodID RenderingRuleSearchRequest_getIntIntPropertyValue;
|
|
|
|
jmethodID RenderingRuleSearchRequest_getStringPropertyValue;
|
|
|
|
jmethodID RenderingRuleSearchRequest_setIntFilter;
|
|
|
|
jmethodID RenderingRuleSearchRequest_setStringFilter;
|
|
|
|
jmethodID RenderingRuleSearchRequest_setBooleanFilter;
|
|
|
|
|
|
|
|
jmethodID RenderingRuleSearchRequest_search;
|
|
|
|
jmethodID RenderingRuleSearchRequest_searchI;
|
|
|
|
|
|
|
|
jclass BinaryMapDataObjectClass;
|
|
|
|
jmethodID BinaryMapDataObject_getPointsLength;
|
|
|
|
jmethodID BinaryMapDataObject_getPoint31YTile;
|
|
|
|
jmethodID BinaryMapDataObject_getPoint31XTile;
|
|
|
|
jmethodID BinaryMapDataObject_getTypes;
|
|
|
|
jmethodID BinaryMapDataObject_getTagValue;
|
|
|
|
|
|
|
|
jclass TagValuePairClass;
|
|
|
|
jfieldID TagValuePair_tag;
|
|
|
|
jfieldID TagValuePair_value;
|
|
|
|
|
|
|
|
jclass RenderingContextClass;
|
|
|
|
|
|
|
|
char debugMessage[1024];
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct RenderingContext {
|
|
|
|
jobject originalRC;
|
2011-10-23 18:41:49 +02:00
|
|
|
jobject androidContext;
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
// public boolean interrupted = false;
|
|
|
|
// boolean highResMode = false;
|
|
|
|
// float mapTextSize = 1;
|
|
|
|
// List<TextDrawInfo> textToDraw = new ArrayList<TextDrawInfo>();
|
|
|
|
// List<IconDrawInfo> iconsToDraw = new ArrayList<IconDrawInfo>();
|
|
|
|
|
|
|
|
float leftX;
|
|
|
|
float topY;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
int zoom;
|
|
|
|
float rotate;
|
|
|
|
float tileDivisor;
|
|
|
|
|
|
|
|
// debug purpose
|
|
|
|
int pointCount ;
|
|
|
|
int pointInsideCount;
|
|
|
|
int visible;
|
|
|
|
int allObjects;
|
|
|
|
|
|
|
|
// use to calculate points
|
|
|
|
float calcX;
|
|
|
|
float calcY;
|
|
|
|
|
|
|
|
float cosRotateTileSize;
|
|
|
|
float sinRotateTileSize;
|
|
|
|
|
|
|
|
int shadowRenderingMode;
|
|
|
|
|
|
|
|
// not expect any shadow
|
|
|
|
int shadowLevelMin;
|
|
|
|
int shadowLevelMax;
|
|
|
|
} RenderingContext;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jfieldID getFid(jclass cls,const char* fieldName, const char* sig )
|
|
|
|
{
|
|
|
|
return env->GetFieldID( cls, fieldName, sig);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void calcPoint(jobject mapObject, jint ind, RenderingContext* rc)
|
|
|
|
{
|
|
|
|
rc -> pointCount ++;
|
|
|
|
|
|
|
|
float tx = env->CallIntMethod( mapObject, BinaryMapDataObject_getPoint31XTile, ind)
|
|
|
|
/ (rc -> tileDivisor);
|
|
|
|
float ty = env->CallIntMethod( mapObject, BinaryMapDataObject_getPoint31YTile, ind)
|
|
|
|
/ (rc -> tileDivisor);
|
|
|
|
|
|
|
|
float dTileX = tx - rc -> leftX;
|
|
|
|
float dTileY = ty - rc -> topY;
|
|
|
|
rc -> calcX = rc -> cosRotateTileSize * dTileX - rc -> sinRotateTileSize * dTileY;
|
|
|
|
rc -> calcY = rc -> sinRotateTileSize * dTileX + rc -> cosRotateTileSize * dTileY;
|
|
|
|
|
|
|
|
if(rc -> calcX >= 0 && rc -> calcX < rc -> width &&
|
|
|
|
rc -> calcY >= 0 && rc -> calcY < rc ->height){
|
|
|
|
rc -> pointInsideCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int getIntPropertyValue(jobject renderingRuleSearch, const char* prop)
|
|
|
|
{
|
|
|
|
jobject all = env->GetObjectField( renderingRuleSearch, RenderingRuleSearchRequest_ALL);
|
|
|
|
jfieldID fid = env->GetFieldID( RenderingRuleStoragePropertiesClass, prop,
|
|
|
|
"Lnet/osmand/render/RenderingRuleProperty;");
|
|
|
|
jobject propObj = env->GetObjectField( all, fid);
|
|
|
|
int res = env->CallIntMethod( renderingRuleSearch, RenderingRuleSearchRequest_getIntPropertyValue, propObj);
|
|
|
|
env->DeleteLocalRef( all);
|
|
|
|
env->DeleteLocalRef( propObj);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
jstring getStringPropertyValue(jobject renderingRuleSearch, const char* prop)
|
|
|
|
{
|
|
|
|
jobject all = env->GetObjectField( renderingRuleSearch, RenderingRuleSearchRequest_ALL);
|
|
|
|
jfieldID fid = env->GetFieldID( RenderingRuleStoragePropertiesClass, prop,
|
|
|
|
"Lnet/osmand/render/RenderingRuleProperty;");
|
|
|
|
jobject propObj = env->GetObjectField( all, fid);
|
|
|
|
jstring res = (jstring) env->CallObjectMethod( renderingRuleSearch, RenderingRuleSearchRequest_getStringPropertyValue, propObj);
|
|
|
|
env->DeleteLocalRef( all);
|
|
|
|
env->DeleteLocalRef( propObj);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIntPropertyFilter(jobject renderingRuleSearch, const char* prop, int filter)
|
|
|
|
{
|
|
|
|
jobject all = env->GetObjectField( renderingRuleSearch, RenderingRuleSearchRequest_ALL);
|
|
|
|
jfieldID fid = env->GetFieldID( RenderingRuleStoragePropertiesClass, prop,
|
|
|
|
"Lnet/osmand/render/RenderingRuleProperty;");
|
|
|
|
jobject propObj = env->GetObjectField( all, fid);
|
|
|
|
env->CallVoidMethod( renderingRuleSearch, RenderingRuleSearchRequest_setIntFilter, propObj, filter);
|
|
|
|
env->DeleteLocalRef( all);
|
|
|
|
env->DeleteLocalRef( propObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float getFloatPropertyValue(jobject renderingRuleSearch, const char* prop)
|
|
|
|
{
|
|
|
|
jobject all = env->GetObjectField( renderingRuleSearch, RenderingRuleSearchRequest_ALL);
|
|
|
|
jfieldID fid = env->GetFieldID( RenderingRuleStoragePropertiesClass, prop,
|
|
|
|
"Lnet/osmand/render/RenderingRuleProperty;");
|
|
|
|
jobject propObj = env->GetObjectField( all, fid);
|
|
|
|
float res = env->CallFloatMethod( renderingRuleSearch, RenderingRuleSearchRequest_getFloatPropertyValue, propObj);
|
|
|
|
env->DeleteLocalRef( all);
|
|
|
|
env->DeleteLocalRef( propObj);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
SkPathEffect* getDashEffect(const char* chars){
|
2011-10-22 14:00:59 +02:00
|
|
|
int i = 0;
|
|
|
|
char fval[10];
|
|
|
|
int flength = 0;
|
2011-10-23 18:09:35 +02:00
|
|
|
float primFloats[20];
|
2011-10-22 14:00:59 +02:00
|
|
|
int floatLen = 0;
|
2011-10-23 18:09:35 +02:00
|
|
|
for(;;i++)
|
2011-10-22 14:00:59 +02:00
|
|
|
{
|
2011-10-23 18:09:35 +02:00
|
|
|
if(chars[i] == 0)
|
2011-10-22 14:00:59 +02:00
|
|
|
{
|
|
|
|
if(flength > 0) { fval[flength] = 0;
|
|
|
|
primFloats[floatLen++] = atof(fval); flength = 0;}
|
2011-10-23 18:09:35 +02:00
|
|
|
break;
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(chars[i] != '_')
|
|
|
|
{
|
|
|
|
// suppose it is a character
|
|
|
|
fval[flength++] = chars[i] ;
|
|
|
|
} else {
|
|
|
|
if(flength > 0) { fval[flength] = 0;
|
|
|
|
primFloats[floatLen++] = atof(fval); flength = 0;}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-10-23 18:09:35 +02:00
|
|
|
return new SkDashPathEffect(primFloats, floatLen, 0);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-23 18:41:49 +02:00
|
|
|
SkBitmap* getNativeBitmap(jobject bmpObj){
|
|
|
|
if(bmpObj == NULL){
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
jclass bmpClass = env->GetObjectClass(bmpObj);
|
|
|
|
SkBitmap* bmp = (SkBitmap*)env->CallIntMethod(bmpObj, env->GetMethodID(bmpClass, "ni", "()I"));
|
|
|
|
env->DeleteLocalRef(bmpClass);
|
|
|
|
return bmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkBitmap* getCachedBitmap(RenderingContext* rc, jstring js)
|
|
|
|
{
|
|
|
|
jobject bmp = env->CallStaticObjectMethod(RenderingIconsClass, RenderingIcons_getIcon, rc->androidContext, js);
|
|
|
|
SkBitmap* res = getNativeBitmap(bmp);
|
|
|
|
env->DeleteLocalRef(bmp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
|
|
|
|
// TODO cache shaders
|
|
|
|
// TODO path effects
|
|
|
|
int updatePaint(jobject renderingRuleSearch, SkPaint* paint, int ind, int area, RenderingContext* rc) {
|
2011-10-22 14:00:59 +02:00
|
|
|
const char* rColor;
|
|
|
|
const char* rStrokeW;
|
|
|
|
const char* rCap;
|
|
|
|
const char* rPathEff;
|
|
|
|
if (ind == 0) {
|
|
|
|
rColor = "R_COLOR";
|
|
|
|
rStrokeW = "R_STROKE_WIDTH";
|
|
|
|
rCap = "R_CAP";
|
|
|
|
rPathEff = "R_PATH_EFFECT";
|
|
|
|
} else if (ind == 1) {
|
|
|
|
rColor = "R_COLOR_2";
|
|
|
|
rStrokeW = "R_STROKE_WIDTH_2";
|
|
|
|
rCap = "R_CAP_2";
|
|
|
|
rPathEff = "R_PATH_EFFECT_2";
|
|
|
|
} else {
|
|
|
|
rColor = "R_COLOR_3";
|
|
|
|
rStrokeW = "R_STROKE_WIDTH_3";
|
|
|
|
rCap = "R_CAP_3";
|
|
|
|
rPathEff = "R_PATH_EFFECT_3";
|
|
|
|
}
|
2011-10-23 18:09:35 +02:00
|
|
|
if (area) {
|
|
|
|
paint->setStyle(SkPaint::kStrokeAndFill_Style);
|
|
|
|
paint->setStrokeWidth(0);
|
|
|
|
} else {
|
2011-10-22 14:00:59 +02:00
|
|
|
float stroke = getFloatPropertyValue(renderingRuleSearch, rStrokeW);
|
|
|
|
if (!(stroke > 0)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-10-22 20:47:30 +02:00
|
|
|
paint->setStyle(SkPaint::kStroke_Style);
|
|
|
|
paint->setStrokeWidth(stroke);
|
2011-10-23 18:09:35 +02:00
|
|
|
jstring capStr = getStringPropertyValue(renderingRuleSearch, rCap);
|
|
|
|
jstring pathEffStr = getStringPropertyValue(renderingRuleSearch, rPathEff);
|
|
|
|
|
|
|
|
if (capStr != NULL && env->GetStringLength(capStr) > 0) {
|
|
|
|
const char* cap = env->GetStringUTFChars(capStr, NULL);
|
|
|
|
if (strcmp("BUTT", cap) == 0) {
|
|
|
|
paint->setStrokeCap(SkPaint::kButt_Cap);
|
|
|
|
} else if (strcmp("ROUND", cap) == 0) {
|
|
|
|
paint->setStrokeCap(SkPaint::kRound_Cap);
|
|
|
|
} else if (strcmp("SQUARE", cap) == 0) {
|
|
|
|
paint->setStrokeCap(SkPaint::kSquare_Cap);
|
|
|
|
}
|
|
|
|
env->ReleaseStringUTFChars(capStr, cap);
|
2011-10-22 14:00:59 +02:00
|
|
|
} else {
|
2011-10-22 20:47:30 +02:00
|
|
|
paint->setStrokeCap(SkPaint::kButt_Cap);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
if (pathEffStr != NULL && env->GetStringLength(pathEffStr) > 0) {
|
|
|
|
const char* pathEff = env->GetStringUTFChars(pathEffStr, NULL);
|
|
|
|
SkPathEffect* p = getDashEffect(pathEff);
|
|
|
|
paint->setPathEffect(p);
|
|
|
|
p->unref();
|
|
|
|
env->ReleaseStringUTFChars(pathEffStr, pathEff);
|
2011-10-22 14:00:59 +02:00
|
|
|
} else {
|
2011-10-23 18:09:35 +02:00
|
|
|
paint->setPathEffect(NULL);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
env->DeleteLocalRef(capStr);
|
|
|
|
env->DeleteLocalRef(pathEffStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int color = getIntPropertyValue(renderingRuleSearch, rColor);
|
|
|
|
paint->setColor(color);
|
|
|
|
|
|
|
|
if (ind == 0) {
|
2011-10-23 18:41:49 +02:00
|
|
|
jstring shader = getStringPropertyValue(renderingRuleSearch, "R_SHADER");
|
|
|
|
if(shader != NULL){
|
|
|
|
SkBitmap* bmp = getCachedBitmap(rc, shader);
|
2011-10-23 19:02:32 +02:00
|
|
|
if(bmp == NULL) {
|
|
|
|
paint->setShader(NULL);
|
|
|
|
} else {
|
|
|
|
paint->setShader(new SkBitmapProcShader(*bmp, SkShader::kRepeat_TileMode,SkShader::kRepeat_TileMode))->
|
2011-10-23 18:41:49 +02:00
|
|
|
unref();
|
2011-10-23 19:02:32 +02:00
|
|
|
}
|
2011-10-23 18:41:49 +02:00
|
|
|
} else {
|
|
|
|
paint->setShader(NULL);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(shader);
|
2011-10-23 18:09:35 +02:00
|
|
|
} else {
|
|
|
|
paint->setShader(NULL);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
// do not check shadow color here
|
|
|
|
if (rc->shadowRenderingMode != 1 || ind != 0) {
|
|
|
|
paint->setLooper(NULL);
|
|
|
|
} else {
|
|
|
|
int shadowColor = getIntPropertyValue(renderingRuleSearch, "R_SHADOW_COLOR");
|
|
|
|
int shadowLayer = getIntPropertyValue(renderingRuleSearch, "R_SHADOW_RADIUS");
|
|
|
|
if (shadowColor == 0) {
|
|
|
|
shadowLayer = 0;
|
|
|
|
}
|
|
|
|
if (shadowLayer > 0) {
|
|
|
|
paint->setLooper(new SkBlurDrawLooper(shadowLayer, 0, 0, shadowColor))->unref();
|
|
|
|
}
|
|
|
|
paint->setLooper(NULL);
|
|
|
|
}
|
|
|
|
return 1;
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-22 20:47:30 +02:00
|
|
|
void drawPolyline(jobject binaryMapDataObject, jobject renderingRuleSearch, SkCanvas* cv, SkPaint* paint,
|
2011-10-22 14:00:59 +02:00
|
|
|
RenderingContext* rc, jobject pair, int layer, int drawOnlyShadow)
|
|
|
|
{
|
|
|
|
if (renderingRuleSearch == NULL || pair == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jint length = env->CallIntMethod( binaryMapDataObject,
|
|
|
|
BinaryMapDataObject_getPointsLength);
|
|
|
|
if (length < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jstring tag = (jstring ) env->GetObjectField( pair, TagValuePair_tag);
|
|
|
|
jstring value = (jstring ) env->GetObjectField( pair, TagValuePair_value);
|
|
|
|
|
|
|
|
// __android_log_print(ANDROID_LOG_WARN, "net.osmand", "About to search");
|
|
|
|
env->CallVoidMethod( renderingRuleSearch,
|
|
|
|
RenderingRuleSearchRequest_setInitialTagValueZoom, tag, value,
|
|
|
|
rc->zoom);
|
|
|
|
setIntPropertyFilter(renderingRuleSearch, "R_LAYER", layer);
|
|
|
|
// TODO oneway
|
|
|
|
// int oneway = 0;
|
|
|
|
//if(rc -> zoom >= 16 && "highway".equals(pair.tag) && MapRenderingTypes.isOneWayWay(obj.getHighwayAttributes())){
|
|
|
|
//strcmp("highway") oneway = 1;
|
|
|
|
//}
|
|
|
|
|
|
|
|
int rendered = env->CallBooleanMethod( renderingRuleSearch,
|
|
|
|
RenderingRuleSearchRequest_search, 2);
|
|
|
|
env->DeleteLocalRef( tag);
|
|
|
|
env->DeleteLocalRef( value);
|
|
|
|
if (!rendered || !updatePaint(renderingRuleSearch, paint, 0, 0, rc)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc->visible++;
|
2011-10-22 20:47:30 +02:00
|
|
|
SkPath path ;
|
2011-10-22 14:00:59 +02:00
|
|
|
int i = 0;
|
|
|
|
for (; i < length; i++) {
|
|
|
|
calcPoint(binaryMapDataObject, i, rc);
|
2011-10-22 20:47:30 +02:00
|
|
|
if (i == 0) {
|
|
|
|
path.moveTo(rc->calcX, rc->calcY);
|
2011-10-22 14:00:59 +02:00
|
|
|
} else {
|
2011-10-22 20:47:30 +02:00
|
|
|
path.lineTo(rc->calcX, rc->calcY);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
}
|
2011-10-22 20:47:30 +02:00
|
|
|
if (i > 0) {
|
2011-10-22 14:00:59 +02:00
|
|
|
if (drawOnlyShadow) {
|
|
|
|
//int shadowColor = render.getIntPropertyValue(render.ALL.R_SHADOW_COLOR);
|
|
|
|
//int shadowRadius = render.getIntPropertyValue(render.ALL.R_SHADOW_RADIUS);
|
|
|
|
//drawPolylineShadow(canvas, rc, path, shadowColor, shadowRadius);
|
|
|
|
} else {
|
2011-10-22 20:47:30 +02:00
|
|
|
cv->drawPath(path, *paint);
|
2011-10-22 14:00:59 +02:00
|
|
|
//if (updatePaint(render, paint, 1, false, rc)) {
|
|
|
|
// canvas.drawPath(path, paint);
|
|
|
|
// if (updatePaint(render, paint, 2, false, rc)) {
|
|
|
|
// canvas.drawPath(path, paint);
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
}
|
2011-10-23 18:09:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void drawPolygon(jobject binaryMapDataObject, jobject renderingRuleSearch, SkCanvas* cv, SkPaint* paint,
|
|
|
|
RenderingContext* rc, jobject pair) {
|
|
|
|
if (renderingRuleSearch == NULL || pair == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jint length = env->CallIntMethod(binaryMapDataObject, BinaryMapDataObject_getPointsLength);
|
|
|
|
if (length <= 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jstring tag = (jstring) env->GetObjectField(pair, TagValuePair_tag);
|
|
|
|
jstring value = (jstring) env->GetObjectField(pair, TagValuePair_value);
|
|
|
|
|
|
|
|
env->CallVoidMethod(renderingRuleSearch, RenderingRuleSearchRequest_setInitialTagValueZoom, tag, value, rc->zoom);
|
|
|
|
|
|
|
|
int rendered = env->CallBooleanMethod(renderingRuleSearch, RenderingRuleSearchRequest_search, 3);
|
|
|
|
env->DeleteLocalRef(tag);
|
|
|
|
env->DeleteLocalRef(value);
|
|
|
|
|
|
|
|
float xText = 0;
|
|
|
|
float yText = 0;
|
|
|
|
if (!rendered || !updatePaint(renderingRuleSearch, paint, 0, 1, rc)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc->visible++;
|
|
|
|
SkPath path;
|
|
|
|
int i = 0;
|
|
|
|
float px = 0;
|
|
|
|
float py = 0;
|
|
|
|
for (; i < length; i++) {
|
|
|
|
calcPoint(binaryMapDataObject, i, rc);
|
|
|
|
if (i == 0) {
|
|
|
|
path.moveTo(rc->calcX, rc->calcY);
|
|
|
|
} else {
|
|
|
|
path.lineTo(rc->calcX, rc->calcY);
|
|
|
|
}
|
|
|
|
xText += px;
|
|
|
|
yText += py;
|
|
|
|
}
|
2011-10-22 14:00:59 +02:00
|
|
|
|
2011-10-23 18:09:35 +02:00
|
|
|
cv->drawPath(path, *paint);
|
|
|
|
if (updatePaint(renderingRuleSearch, paint, 1, 0, rc)) {
|
|
|
|
cv->drawPath(path, *paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO polygon text
|
|
|
|
// String name = obj.getName();
|
|
|
|
// if(name != null){
|
|
|
|
// drawPointText(render, rc, pair, xText / len, yText / len, name);
|
|
|
|
// }
|
|
|
|
// }
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
|
2011-10-23 19:02:32 +02:00
|
|
|
// 0 - normal, -1 - under, 1 - bridge,over
|
|
|
|
int getNegativeWayLayer(int type) {
|
|
|
|
int i = (3 & (type >> 12));
|
|
|
|
if (i == 1) {
|
|
|
|
return -1;
|
|
|
|
} else if (i == 2) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-10-22 20:47:30 +02:00
|
|
|
void drawObject(RenderingContext* rc, jobject binaryMapDataObject, SkCanvas* cv,
|
|
|
|
jobject renderingRuleSearch, SkPaint* paint, int l, int renderText, int drawOnlyShadow) {
|
2011-10-22 14:00:59 +02:00
|
|
|
rc -> allObjects++;
|
|
|
|
if (env->IsInstanceOf( binaryMapDataObject, MultiPolygonClass)) {
|
|
|
|
//if(!drawOnlyShadow){
|
|
|
|
// drawMultiPolygon(obj, render, canvas, rc);
|
|
|
|
//}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jintArray types = (jintArray) env->CallObjectMethod( binaryMapDataObject, BinaryMapDataObject_getTypes);
|
|
|
|
jint mainType;
|
|
|
|
env->GetIntArrayRegion( types, l, 1, &mainType);
|
|
|
|
int t = mainType & 3;
|
|
|
|
env->DeleteLocalRef( types);
|
|
|
|
|
|
|
|
jobject pair = env->CallObjectMethod( binaryMapDataObject, BinaryMapDataObject_getTagValue, l);
|
|
|
|
if( t == 1 && !drawOnlyShadow) {
|
|
|
|
// point
|
|
|
|
|
|
|
|
// drawPoint(obj, render, canvas, rc, pair, renderText);
|
|
|
|
} else if(t == 2) {
|
|
|
|
// polyline
|
2011-10-23 19:02:32 +02:00
|
|
|
int layer = getNegativeWayLayer(mainType);
|
2011-10-22 14:00:59 +02:00
|
|
|
// __android_log_print(ANDROID_LOG_WARN, "net.osmand", "Draw polyline");
|
|
|
|
drawPolyline(binaryMapDataObject, renderingRuleSearch, cv, paint, rc, pair, layer, drawOnlyShadow);
|
|
|
|
} else if(t == 3 && !drawOnlyShadow) {
|
|
|
|
// polygon
|
2011-10-23 18:09:35 +02:00
|
|
|
drawPolygon(binaryMapDataObject, renderingRuleSearch, cv, paint, rc, pair);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
env->DeleteLocalRef( pair);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void copyRenderingContext(jobject orc, RenderingContext* rc)
|
|
|
|
{
|
|
|
|
rc->leftX = env->GetFloatField( orc, getFid( RenderingContextClass, "leftX", "F" ) );
|
|
|
|
rc->topY = env->GetFloatField( orc, getFid( RenderingContextClass, "topY", "F" ) );
|
|
|
|
rc->width = env->GetIntField( orc, getFid( RenderingContextClass, "width", "I" ) );
|
|
|
|
rc->height = env->GetIntField( orc, getFid( RenderingContextClass, "height", "I" ) );
|
|
|
|
|
|
|
|
|
|
|
|
rc->zoom = env->GetIntField( orc, getFid( RenderingContextClass, "zoom", "I" ) );
|
|
|
|
rc->rotate = env->GetFloatField( orc, getFid( RenderingContextClass, "rotate", "F" ) );
|
|
|
|
rc->tileDivisor = env->GetFloatField( orc, getFid( RenderingContextClass, "tileDivisor", "F" ) );
|
|
|
|
|
|
|
|
rc->pointCount = env->GetIntField( orc, getFid( RenderingContextClass, "pointCount", "I" ) );
|
|
|
|
rc->pointInsideCount = env->GetIntField( orc, getFid( RenderingContextClass, "pointInsideCount", "I" ) );
|
|
|
|
rc->visible = env->GetIntField( orc, getFid( RenderingContextClass, "visible", "I" ) );
|
|
|
|
rc->allObjects = env->GetIntField( orc, getFid( RenderingContextClass, "allObjects", "I" ) );
|
|
|
|
|
|
|
|
rc->cosRotateTileSize = env->GetFloatField( orc, getFid( RenderingContextClass, "cosRotateTileSize", "F" ) );
|
|
|
|
rc->sinRotateTileSize = env->GetFloatField( orc, getFid( RenderingContextClass, "sinRotateTileSize", "F" ) );
|
|
|
|
|
|
|
|
rc->shadowRenderingMode = env->GetIntField( orc, getFid( RenderingContextClass, "shadowRenderingMode", "I" ) );
|
|
|
|
rc->shadowLevelMin = env->GetIntField( orc, getFid( RenderingContextClass, "shadowLevelMin", "I" ) );
|
|
|
|
rc->shadowLevelMax = env->GetIntField( orc, getFid( RenderingContextClass, "shadowLevelMax", "I" ) );
|
2011-10-23 18:41:49 +02:00
|
|
|
rc->androidContext = env->GetObjectField(orc, getFid( RenderingContextClass, "ctx", "Landroid/content/Context;"));
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
rc->originalRC = orc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void mergeRenderingContext(jobject orc, RenderingContext* rc)
|
|
|
|
{
|
|
|
|
env->SetIntField( orc, getFid(RenderingContextClass, "pointCount", "I" ) , rc->pointCount);
|
|
|
|
env->SetIntField( orc, getFid(RenderingContextClass, "pointInsideCount", "I" ) , rc->pointInsideCount);
|
|
|
|
env->SetIntField( orc, getFid(RenderingContextClass, "visible", "I" ) , rc->visible);
|
|
|
|
env->SetIntField( orc, getFid(RenderingContextClass, "allObjects", "I" ) , rc->allObjects);
|
2011-10-23 18:41:49 +02:00
|
|
|
env->DeleteLocalRef(rc->androidContext);
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
jclass globalRef(jobject o)
|
|
|
|
{
|
|
|
|
return (jclass) env->NewGlobalRef( o);
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject globalObj(jobject o)
|
|
|
|
{
|
|
|
|
return env->NewGlobalRef( o);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initLibrary(jobject rc)
|
|
|
|
{
|
|
|
|
MultiPolygonClass = globalRef(env->FindClass( "net/osmand/osm/MultyPolygon"));
|
|
|
|
|
|
|
|
PathClass = globalRef(env->FindClass( "android/graphics/Path"));
|
|
|
|
Path_init = env->GetMethodID( PathClass, "<init>", "()V" );
|
|
|
|
Path_moveTo = env->GetMethodID( PathClass, "moveTo", "(FF)V" );
|
|
|
|
Path_lineTo = env->GetMethodID( PathClass, "lineTo", "(FF)V" );
|
|
|
|
|
|
|
|
CanvasClass = globalRef(env->FindClass( "android/graphics/Canvas"));
|
|
|
|
Canvas_drawPath = env->GetMethodID( CanvasClass, "drawPath",
|
|
|
|
"(Landroid/graphics/Path;Landroid/graphics/Paint;)V" );
|
2011-10-22 20:47:30 +02:00
|
|
|
Canvas_nativeCanvas = env->GetFieldID( CanvasClass, "mNativeCanvas","I" );
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
RenderingContextClass = globalRef(env->GetObjectClass( rc));
|
|
|
|
|
2011-10-23 18:41:49 +02:00
|
|
|
RenderingIconsClass = globalRef(env->FindClass( "net/osmand/plus/render/RenderingIcons"));
|
|
|
|
RenderingIcons_getIcon = env->GetStaticMethodID(RenderingIconsClass, "getIcon","(Landroid/content/Context;Ljava/lang/String;)Landroid/graphics/Bitmap;");
|
|
|
|
|
2011-10-22 14:00:59 +02:00
|
|
|
BinaryMapDataObjectClass = globalRef(env->FindClass( "net/osmand/binary/BinaryMapDataObject"));
|
|
|
|
BinaryMapDataObject_getPointsLength = env->GetMethodID( BinaryMapDataObjectClass,"getPointsLength","()I");
|
|
|
|
BinaryMapDataObject_getPoint31YTile = env->GetMethodID( BinaryMapDataObjectClass,"getPoint31YTile","(I)I");
|
|
|
|
BinaryMapDataObject_getPoint31XTile = env->GetMethodID( BinaryMapDataObjectClass,"getPoint31XTile","(I)I");
|
|
|
|
BinaryMapDataObject_getTypes = env->GetMethodID( BinaryMapDataObjectClass,"getTypes","()[I");
|
|
|
|
BinaryMapDataObject_getTagValue = env->GetMethodID( BinaryMapDataObjectClass,"getTagValue",
|
|
|
|
"(I)Lnet/osmand/binary/BinaryMapIndexReader$TagValuePair;");
|
|
|
|
|
|
|
|
TagValuePairClass = globalRef(env->FindClass( "net/osmand/binary/BinaryMapIndexReader$TagValuePair"));
|
|
|
|
TagValuePair_tag = env->GetFieldID( TagValuePairClass, "tag", "Ljava/lang/String;");
|
|
|
|
TagValuePair_value= env->GetFieldID( TagValuePairClass, "value", "Ljava/lang/String;");
|
|
|
|
|
|
|
|
RenderingRuleStoragePropertiesClass =
|
|
|
|
globalRef(env->FindClass( "net/osmand/render/RenderingRuleStorageProperties"));
|
|
|
|
RenderingRulePropertyClass = globalRef(env->FindClass( "net/osmand/render/RenderingRuleProperty"));
|
|
|
|
|
|
|
|
|
|
|
|
RenderingRuleSearchRequestClass = globalRef(env->FindClass( "net/osmand/render/RenderingRuleSearchRequest"));
|
|
|
|
RenderingRuleSearchRequest_setInitialTagValueZoom =
|
|
|
|
env->GetMethodID( RenderingRuleSearchRequestClass,"setInitialTagValueZoom",
|
|
|
|
"(Ljava/lang/String;Ljava/lang/String;I)V");
|
|
|
|
RenderingRuleSearchRequest_ALL = env->GetFieldID( RenderingRuleSearchRequestClass, "ALL",
|
|
|
|
"Lnet/osmand/render/RenderingRuleStorageProperties;");
|
|
|
|
RenderingRuleSearchRequest_getIntPropertyValue = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"getIntPropertyValue", "(Lnet/osmand/render/RenderingRuleProperty;)I");
|
|
|
|
RenderingRuleSearchRequest_getIntIntPropertyValue = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"getIntPropertyValue", "(Lnet/osmand/render/RenderingRuleProperty;I)I");
|
|
|
|
RenderingRuleSearchRequest_getFloatPropertyValue = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"getFloatPropertyValue", "(Lnet/osmand/render/RenderingRuleProperty;)F");
|
|
|
|
RenderingRuleSearchRequest_getStringPropertyValue = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"getStringPropertyValue", "(Lnet/osmand/render/RenderingRuleProperty;)Ljava/lang/String;");
|
|
|
|
RenderingRuleSearchRequest_setIntFilter = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"setIntFilter", "(Lnet/osmand/render/RenderingRuleProperty;I)V");
|
|
|
|
RenderingRuleSearchRequest_setStringFilter = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"setStringFilter", "(Lnet/osmand/render/RenderingRuleProperty;Ljava/lang/String;)V");
|
|
|
|
RenderingRuleSearchRequest_setBooleanFilter = env->GetMethodID( RenderingRuleSearchRequestClass,
|
|
|
|
"setBooleanFilter", "(Lnet/osmand/render/RenderingRuleProperty;Z)V");
|
|
|
|
RenderingRuleSearchRequest_search = env->GetMethodID( RenderingRuleSearchRequestClass, "search", "(I)Z");
|
|
|
|
RenderingRuleSearchRequest_searchI = env->GetMethodID( RenderingRuleSearchRequestClass, "search", "(IZ)Z");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void unloadLibrary()
|
|
|
|
{
|
|
|
|
env->DeleteGlobalRef( MultiPolygonClass );
|
|
|
|
env->DeleteGlobalRef( PathClass );
|
|
|
|
env->DeleteGlobalRef( CanvasClass );
|
|
|
|
env->DeleteGlobalRef( RenderingContextClass );
|
2011-10-23 18:41:49 +02:00
|
|
|
env->DeleteGlobalRef( RenderingIconsClass );
|
2011-10-22 14:00:59 +02:00
|
|
|
env->DeleteGlobalRef( TagValuePairClass);
|
|
|
|
env->DeleteGlobalRef( RenderingRuleSearchRequestClass);
|
|
|
|
env->DeleteGlobalRef( RenderingRulePropertyClass);
|
|
|
|
env->DeleteGlobalRef( RenderingRuleStoragePropertiesClass);
|
|
|
|
env->DeleteGlobalRef( BinaryMapDataObjectClass );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_generateRendering( JNIEnv* ienv,
|
2011-10-22 20:47:30 +02:00
|
|
|
jobject obj, jobject renderingContext, jobjectArray binaryMapDataObjects, jobject bmpObj,
|
|
|
|
jboolean useEnglishNames, jobject renderingRuleSearchRequest, jint defaultColor) {
|
2011-10-22 14:00:59 +02:00
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Initializing rendering");
|
|
|
|
size_t i = 0;
|
|
|
|
if(!env) {
|
|
|
|
env = ienv;
|
|
|
|
initLibrary(renderingContext);
|
|
|
|
}
|
2011-10-22 20:47:30 +02:00
|
|
|
|
2011-10-23 18:41:49 +02:00
|
|
|
|
2011-10-22 20:47:30 +02:00
|
|
|
SkPaint* paint = new SkPaint;
|
|
|
|
paint->setAntiAlias(true);
|
2011-10-23 18:41:49 +02:00
|
|
|
|
|
|
|
SkBitmap* bmp = getNativeBitmap(bmpObj);
|
2011-10-22 20:47:30 +02:00
|
|
|
SkCanvas* canvas = new SkCanvas(*bmp);
|
|
|
|
|
2011-10-23 16:47:28 +02:00
|
|
|
sprintf(debugMessage, "Image w:%d h:%d rb: %d!", bmp->width(), bmp->height(), bmp->rowBytes());
|
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
|
|
|
|
sprintf(debugMessage, "Image h:%d sz:%d bperpix:%d shiftperpix:%d!",
|
|
|
|
bmp->height(), bmp->getSize(), bmp->bytesPerPixel(), bmp->shiftPerPixel());
|
2011-10-22 20:47:30 +02:00
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
|
2011-10-22 14:00:59 +02:00
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Classes and methods are loaded");
|
2011-10-22 20:47:30 +02:00
|
|
|
canvas->drawColor(defaultColor);
|
2011-10-22 14:00:59 +02:00
|
|
|
const size_t size = env->GetArrayLength( binaryMapDataObjects);
|
|
|
|
RenderingContext rc;
|
|
|
|
|
|
|
|
copyRenderingContext(renderingContext, &rc);
|
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Rendering image");
|
|
|
|
|
|
|
|
for(; i < size; i++)
|
|
|
|
{
|
|
|
|
jobject binaryMapDataObject = (jobject) env->GetObjectArrayElement( binaryMapDataObjects, i);
|
|
|
|
jintArray types = (jintArray) env->CallObjectMethod( binaryMapDataObject, BinaryMapDataObject_getTypes);
|
|
|
|
// check multipolygon?
|
|
|
|
if (types != NULL) {
|
|
|
|
jint sizeTypes = env->GetArrayLength( types);
|
|
|
|
env->DeleteLocalRef( types);
|
|
|
|
int j = 0;
|
|
|
|
for (; j < sizeTypes; j++) {
|
2011-10-22 20:47:30 +02:00
|
|
|
drawObject(&rc, binaryMapDataObject, canvas, renderingRuleSearchRequest, paint, j, 1, 0);
|
2011-10-22 14:00:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
env->DeleteLocalRef( binaryMapDataObject);
|
2011-10-22 20:47:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
delete paint;
|
|
|
|
delete canvas;
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "End Rendering image");
|
|
|
|
|
2011-10-22 20:47:30 +02:00
|
|
|
sprintf(debugMessage, "Hello android %d", size);
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
// get an object string
|
2011-10-22 20:47:30 +02:00
|
|
|
jstring result = env->NewStringUTF( debugMessage);
|
2011-10-22 14:00:59 +02:00
|
|
|
|
|
|
|
mergeRenderingContext(renderingContext, &rc);
|
|
|
|
|
|
|
|
// unloadLibrary();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|