Calculate text collisions properly

This commit is contained in:
Victor Shcherb 2011-10-26 14:32:35 +02:00
parent 6f9fdb2b18
commit 4fd9f75b69
6 changed files with 107 additions and 53 deletions

View file

@ -8,6 +8,14 @@
#include <SkPath.h>
#include <SkBitmap.h>
//#define DEBUG_NAT_OPERATIONS
#ifdef DEBUG_NAT_OPERATIONS
#define NAT_COUNT(rc, op) rc->nativeOperations.pause(); op; rc->nativeOperations.start()
#else
#define NAT_COUNT(rc, op) op;
#endif
JNIEnv* env;
const std::string EMPTY_STRING;
@ -72,32 +80,56 @@ jfieldID getFid(jclass cls,const char* fieldName, const char* sig )
return env->GetFieldID( cls, fieldName, sig);
}
class timer {
class watcher {
int elapsedTime;
timeval startInit;
timeval endInit;
bool enableFlag;
// timeval startInit;
// timeval endInit;
timespec startInit;
timespec endInit;
bool run;
public:
timer() {
watcher() {
elapsedTime = 0;
enableFlag = true;
}
void enable(){
enableFlag = true;
}
void disable(){
pause();
enableFlag = false;
}
void start() {
if(!enableFlag){
return;
}
if (!run) {
gettimeofday(&startInit, NULL);
clock_gettime(CLOCK_MONOTONIC, &startInit);
// gettimeofday(&startInit, NULL);
}
run = true;
}
void pause() {
if (run) {
gettimeofday(&endInit, NULL);
elapsedTime += (endInit.tv_sec * 1000 + endInit.tv_usec / 1000)
- (startInit.tv_sec * 1000 + startInit.tv_usec / 1000);
if (!run) {
return;
}
clock_gettime(CLOCK_MONOTONIC, &endInit );
// gettimeofday(&endInit, NULL);
int sec = endInit.tv_sec - startInit.tv_sec;
if(sec > 0){
elapsedTime += 1e9 * sec;
}
elapsedTime += endInit.tv_nsec - startInit.tv_nsec ;
// elapsedTime += (endInit.tv_sec * 1000 + endInit.tv_usec / 1000)
// - (startInit.tv_sec * 1000 + startInit.tv_usec / 1000);
run = false;
}
int getElapsedTime() {
pause();
return elapsedTime;
return elapsedTime / 1e6;
}
};
@ -126,8 +158,8 @@ struct RenderingContext {
int pointInsideCount;
int visible;
int allObjects;
timer textRendering;
timer nativeOperations;
watcher textRendering;
watcher nativeOperations;
// use to calculate points
float calcX;

View file

@ -22,7 +22,6 @@
#include "textdraw.cpp"
#include "mapObjects.cpp"
#define NAT_COUNT(rc, op) rc->nativeOperations.pause(); op; rc->nativeOperations.start()
char debugMessage[1024];
@ -210,6 +209,9 @@ void drawPointText(RenderingRuleSearchRequest* req, RenderingContext* rc, std::s
if (req->getIntPropertyValue(req->props()->R_TEXT_SIZE) > 0) {
TextDrawInfo* text = new TextDrawInfo(ref);
fillTextProperties(text, req, xText, yText);
if (path != NULL) {
text->path = new SkPath(*path);
}
rc->textToDraw.push_back(text);
}
}
@ -692,16 +694,6 @@ std::hash_map<int, std::vector<int> > sortObjectsByProperOrder(std::vector <Base
return orderMap;
}
int objCount = 0;
void objectDrawn(bool notify = false)
{
if (objCount++ > 25) {
// TODO notification
//notifyListeners(notifyList);
objCount = 0;
}
}
void doRendering(std::vector <BaseMapDataObject* > mapDataObjects, SkCanvas* canvas, SkPaint* paint,
RenderingRuleSearchRequest* req, RenderingContext* rc) {
// put in order map
@ -731,7 +723,6 @@ void doRendering(std::vector <BaseMapDataObject* > mapDataObjects, SkCanvas* can
// show text only for main type
drawObject(rc, mapObject, canvas, req, paint, l, l == 0, true);
objectDrawn();
}
}
shadowDrawn = true;
@ -746,8 +737,6 @@ void doRendering(std::vector <BaseMapDataObject* > mapDataObjects, SkCanvas* can
BaseMapDataObject* mapObject = mapDataObjects.at(ind);
// show text only for main type
drawObject(rc, mapObject, canvas, req, paint, l, l == 0, false);
objCount++;
objectDrawn();
}
if (rc->interrupted()) {
@ -756,11 +745,9 @@ void doRendering(std::vector <BaseMapDataObject* > mapDataObjects, SkCanvas* can
}
objectDrawn(true);
drawIconsOverCanvas(rc, canvas);
rc->textRendering.start();
objectDrawn(true);
drawTextOverCanvas(rc, canvas);
rc->textRendering.pause();
}
@ -786,7 +773,7 @@ JNIEXPORT jstring JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_genera
paint->setAntiAlias(true);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Initializing rendering");
timer initObjects;
watcher initObjects;
initObjects.start();
@ -815,8 +802,11 @@ JNIEXPORT jstring JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_genera
delete req;
deleteObjects(mapDataObjects);
sprintf(debugMessage, "Native ok (init %d, native op %d) ", initObjects.getElapsedTime(),
rc.nativeOperations.getElapsedTime());
#ifdef DEBUG_NAT_OPERATIONS
sprintf(debugMessage, "Native ok (init %d, native op %d) ", initObjects.getElapsedTime(), rc.nativeOperations.getElapsedTime());
#else
sprintf(debugMessage, "Native ok (init %d, rendering %d) ", initObjects.getElapsedTime(), rc.nativeOperations.getElapsedTime());
#endif
jstring result = env->NewStringUTF( debugMessage);
// unloadLibrary();

View file

@ -191,16 +191,10 @@ void drawWrappedText(RenderingContext* rc, SkCanvas* cv, TextDrawInfo* text, flo
pos++;
}
if(lastSpace == -1) {
rc->nativeOperations.pause();
drawTextOnCanvas(cv, text->text.substr(start, pos),
text->centerX, text->centerY + line * (textSize + 2), paintText, text->textShadow);
rc->nativeOperations.start();
NAT_COUNT(rc, drawTextOnCanvas(cv, text->text.substr(start, pos), text->centerX, text->centerY + line * (textSize + 2), paintText, text->textShadow));
start = pos;
} else {
rc->nativeOperations.pause();
drawTextOnCanvas(cv, text->text.substr(start, lastSpace),
text->centerX, text->centerY + line * (textSize + 2), paintText, text->textShadow);
rc->nativeOperations.start();
NAT_COUNT(rc, drawTextOnCanvas(cv, text->text.substr(start, lastSpace), text->centerX, text->centerY + line * (textSize + 2), paintText, text->textShadow));
start = lastSpace + 1;
limit += (start - pos) - 1;
}
@ -208,20 +202,31 @@ void drawWrappedText(RenderingContext* rc, SkCanvas* cv, TextDrawInfo* text, flo
}
} else {
rc->nativeOperations.pause();
drawTextOnCanvas(cv, text->text, text->centerX, text->centerY, paintText, text->textShadow);
rc->nativeOperations.start();
NAT_COUNT(rc, drawTextOnCanvas(cv, text->text, text->centerX, text->centerY, paintText, text->textShadow));
}
}
bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
// TODO rotate bounds for shields?
if (!p->drawOnPath || p->path == NULL) {
if(p->path == NULL) {
return true;
}
int len = p->path->countPoints();
SkPoint points[len];
p->path->getPoints(points, len);
if (!p->drawOnPath) {
// simply calculate rotation of path used for shields
p->vOffset -= p->textSize / 2 - 1;
float px = 0;
float py = 0;
for (int i = 1; i < len; i++) {
px += points[i].fX - points[i - 1].fX;
py += points[i].fY - points[i - 1].fY;
}
if (px != 0 || py != 0) {
p->pathRotate = std::atan2(py, px) * 180 / M_PI;
}
return true;
}
bool inverse = false;
float roadLength = 0;
@ -229,7 +234,11 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
float visibleRoadLength = 0;
float textw = p->bounds.width();
int i;
int startVisible = 1;
int startVisible = 0;
std::vector<float> distances;
distances.resize(roadLength, 0);
float normalTextLen = 1.5 * textw;
for (i = 0; i < len; i++) {
bool inside = points[i].fX >= 0 && points[i].fX <= rc->width &&
points[i].fY >= 0 && points[i].fY <= rc->height;
@ -237,18 +246,20 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
float d = std::sqrt(
(points[i].fX - points[i - 1].fX) * (points[i].fX - points[i - 1].fX)
+ (points[i].fY - points[i - 1].fY) * (points[i].fY - points[i - 1].fY));
distances.push_back(d);
roadLength += d;
if(inside) {
visibleRoadLength += d;
if(!prevInside) {
startVisible = i - 1;
}
} else if(!prevInside) {
if(visibleRoadLength >= 1.5 * textw) {
} else if(prevInside) {
if(visibleRoadLength >= normalTextLen) {
break;
}
visibleRoadLength = 0;
}
}
prevInside = inside;
}
@ -257,9 +268,27 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
}
int startInd = 0;
int endInd = len;
if(textw < visibleRoadLength) {
startInd = startVisible - 1;
if(textw < visibleRoadLength && i - startVisible > 1) {
startInd = startVisible;
endInd = i;
// display long road name in center
if (visibleRoadLength > 3 * textw) {
bool ch ;
do {
ch = false;
if(endInd - startInd > 2 && visibleRoadLength - distances[startInd] > normalTextLen){
visibleRoadLength -= distances.at(startInd);
startInd++;
ch = true;
}
if(endInd - startInd > 2 && visibleRoadLength - distances[endInd - 2] > normalTextLen){
visibleRoadLength -= distances.at(endInd - 2);
endInd--;
ch = true;
}
} while(ch);
}
}
// shrink path to display more text
if (startInd > 0 || endInd < len) {
@ -369,10 +398,12 @@ bool findTextIntersection(SkCanvas* cv, RenderingContext* rc, quad_tree<TextDraw
SkRect boundsSearch = text->bounds;
float v = -getDensityValue(rc, std::max(5.0f, text->minDistance));
// TODO min distance different !
boundsSearch.inset(v, v);
// for text purposes
// drawTestBox(cv, text, paintIcon, paintText);
boundIntersections.query_in_box(boundsSearch, search);
for (uint i = 0; i < search.size(); i++) {
TextDrawInfo* t = search.at(i);
@ -436,6 +467,9 @@ void drawTextOverCanvas(RenderingContext* rc, SkCanvas* cv) {
// calculate if there is intersection
bool intersects = findTextIntersection(cv, rc, boundsIntersect, text, &paintText, &paintIcon);
if (!intersects) {
if(rc->interrupted()){
return;
}
if (text->drawOnPath && text->path != NULL) {
if (text->textShadow > 0) {
paintText.setColor(WHITE_COLOR);

Binary file not shown.

View file

@ -448,9 +448,7 @@ public class MapRenderRepositories {
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp, prefs.USE_ENGLISH_NAMES.get(), renderingReq,
notifyList, storage.getBgColor(nightMode), app.getSettings().NATIVE_RENDERING.get());
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
if(currentRenderingContext != null) {
currentRenderingContext.ended = true;
}
currentRenderingContext.ended = true;
if (checkWhetherInterrupted()) {
currentRenderingContext = null;
return;

View file

@ -44,7 +44,6 @@ import android.graphics.Paint.Style;
import android.graphics.Shader.TileMode;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.util.FloatMath;
@ -320,6 +319,7 @@ public class OsmandRenderer {
}
String res = NativeOsmandLibrary.generateRendering(rc, array, bmp, useEnglishNames, render, defaultColor);
rc.ended = true;
notifyListeners(notifyList);
long time = System.currentTimeMillis() - now;
rc.renderingDebugInfo = String.format("Rendering done in %s (%s text) ms\n"
+ "(%s points, %s points inside, %s objects visile from %s)\n" + res,//$NON-NLS-1$