Calculate box correctly
This commit is contained in:
parent
91810f52d5
commit
00280553a6
6 changed files with 167 additions and 85 deletions
|
@ -31,14 +31,13 @@ public :
|
|||
|
||||
TextDrawInfo(std::string itext) {
|
||||
text = itext;
|
||||
drawOnPath = NULL;
|
||||
drawOnPath = false;
|
||||
path = NULL;
|
||||
pathRotate = 0;
|
||||
}
|
||||
SkPath* drawOnPath;
|
||||
SkRect bounds;
|
||||
float vOffset ;
|
||||
float centerX;
|
||||
float centerY;
|
||||
float pathRotate;
|
||||
|
||||
float textSize ;
|
||||
float minDistance ;
|
||||
|
@ -49,9 +48,15 @@ public :
|
|||
std::string shieldRes;
|
||||
int textOrder;
|
||||
|
||||
bool drawOnPath;
|
||||
SkPath* path;
|
||||
float pathRotate;
|
||||
float vOffset ;
|
||||
float hOffset ;
|
||||
|
||||
~TextDrawInfo() {
|
||||
if (drawOnPath != NULL) {
|
||||
delete drawOnPath;
|
||||
if (path != NULL) {
|
||||
delete path;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -187,10 +187,7 @@ int updatePaint(RenderingRuleSearchRequest* req, SkPaint* paint, int ind, int ar
|
|||
}
|
||||
|
||||
void drawPointText(RenderingRuleSearchRequest* req, RenderingContext* rc, std::string tag, std::string value,
|
||||
float xText, float yText, std::string name,
|
||||
// line text properties
|
||||
SkPath* path, float pathRotate, float roadLength, float xCenter, float yCenter,
|
||||
SkPaint* paintText)
|
||||
float xText, float yText, std::string name, SkPath* path)
|
||||
{
|
||||
if (name.at(0) == REF_CHAR) {
|
||||
std::string ref = name.substr(1);
|
||||
|
@ -223,29 +220,16 @@ void drawPointText(RenderingRuleSearchRequest* req, RenderingContext* rc, std::s
|
|||
req->setBooleanFilter(req->props()->R_REF, false);
|
||||
if (req->searchRule(RenderingRulesStorage::TEXT_RULES) &&
|
||||
req->getIntPropertyValue(req->props()->R_TEXT_SIZE) > 0) {
|
||||
if (path == NULL || req->getIntPropertyValue(req->props()->R_TEXT_ON_PATH, 0) == 0) {
|
||||
TextDrawInfo* info = new TextDrawInfo(name);
|
||||
fillTextProperties(info, req, xText, yText);
|
||||
rc->textToDraw.push_back(info);
|
||||
} else {
|
||||
paintText->setTextSize(req->getIntPropertyValue(req->props()->R_TEXT_SIZE) > 0);
|
||||
if (paintText->measureText(name.c_str(), name.size()) < roadLength) {
|
||||
TextDrawInfo* text = new TextDrawInfo(name);
|
||||
fillTextProperties(text, req, xCenter / 2, yCenter / 2);
|
||||
text->pathRotate = pathRotate;
|
||||
text->drawOnPath = new SkPath(*path);
|
||||
int strokeWidth = req->getIntPropertyValue(req->props()->R_TEXT_SIZE);
|
||||
text->vOffset = strokeWidth / 2 - 1;
|
||||
rc->textToDraw.push_back(text);
|
||||
}
|
||||
TextDrawInfo* info = new TextDrawInfo(name);
|
||||
info->drawOnPath = (path != NULL) && (req->getIntPropertyValue(req->props()->R_TEXT_ON_PATH, 0) > 0);
|
||||
if (path != NULL) {
|
||||
info->path = new SkPath(*path);
|
||||
}
|
||||
}
|
||||
fillTextProperties(info, req, xText, yText);
|
||||
rc->textToDraw.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPointText(RenderingRuleSearchRequest* req, RenderingContext* rc, std::string tag, std::string value,
|
||||
float xText, float yText, std::string name){
|
||||
drawPointText(req, rc, tag, value, xText, yText, name, NULL, 0, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void drawPolylineShadow(SkCanvas* cv, SkPaint* paint, RenderingContext* rc, SkPath* path, int shadowColor,
|
||||
int shadowRadius) {
|
||||
|
@ -340,42 +324,18 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
|
|||
rc->visible++;
|
||||
SkPath path;
|
||||
int i = 0;
|
||||
float pathRotate = 0;
|
||||
float roadLength = 0;
|
||||
bool inverse = false;
|
||||
float xPrev = 0;
|
||||
float yPrev = 0;
|
||||
float xMid = 0;
|
||||
float yMid = 0;
|
||||
SkPoint middlePoint;
|
||||
int middle = length / 2;
|
||||
for (; i < length; i++) {
|
||||
calcPoint(mObj, i, rc);
|
||||
if(i == 0 || i == length -1){
|
||||
xMid += rc->calcX;
|
||||
yMid += rc->calcY;
|
||||
}
|
||||
if (i == 0) {
|
||||
path.moveTo(rc->calcX, rc->calcY);
|
||||
} else {
|
||||
roadLength += std::sqrt((rc->calcX - xPrev) * (rc->calcX - xPrev) +
|
||||
(rc->calcY - yPrev) * (rc->calcY - yPrev));
|
||||
if(i == middle){
|
||||
middlePoint.set(rc->calcX, rc->calcY);
|
||||
float rot = - std::atan2(rc->calcX - xPrev, rc->calcY - yPrev) * 180 / M_PI;
|
||||
if (rot < 0) {
|
||||
rot += 360;
|
||||
}
|
||||
if (rot < 180) {
|
||||
rot += 180;
|
||||
inverse = true;
|
||||
}
|
||||
pathRotate = (float) rot;
|
||||
}
|
||||
path.lineTo(rc->calcX, rc->calcY);
|
||||
}
|
||||
xPrev = rc->calcX;
|
||||
yPrev = rc->calcY;
|
||||
}
|
||||
if (i > 0) {
|
||||
if (drawOnlyShadow) {
|
||||
|
@ -394,21 +354,8 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
|
|||
drawOneWayPaints(cv, &path);
|
||||
}
|
||||
if (!drawOnlyShadow && mObj->name.length() > 0) {
|
||||
if (inverse) {
|
||||
path.rewind();
|
||||
bool st = true;
|
||||
for (i = length - 1; i >= 0; i--) {
|
||||
calcPoint(mObj, i, rc);
|
||||
if (st) {
|
||||
st = false;
|
||||
path.moveTo(rc->calcX, rc->calcY);
|
||||
} else {
|
||||
path.lineTo(rc->calcX, rc->calcY);
|
||||
}
|
||||
}
|
||||
}
|
||||
drawPointText(req, rc,pair.first, pair.second, middlePoint.fX, middlePoint.fY, mObj->name,
|
||||
&path, pathRotate, roadLength, xMid, yMid, paint);
|
||||
&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +395,7 @@ void drawMultiPolygon(MultiPolygonObject* mapObject,RenderingRuleSearchRequest*
|
|||
if (cnt > 0) {
|
||||
std::string name = mapObject->names.at(i);
|
||||
if (name.length() > 0) {
|
||||
drawPointText(req, rc, mapObject->tag, mapObject->value, xText / cnt, yText / cnt, name);
|
||||
drawPointText(req, rc, mapObject->tag, mapObject->value, xText / cnt, yText / cnt, name, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +448,7 @@ void drawPolygon(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas*
|
|||
}
|
||||
std::string name = mObj->name;
|
||||
if (name.length() > 0) {
|
||||
drawPointText(req, rc, tag, value, xText / length, yText / length, name);
|
||||
drawPointText(req, rc, tag, value, xText / length, yText / length, name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,7 +494,7 @@ void drawPoint(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas* c
|
|||
rc->iconsToDraw.push_back(ico);
|
||||
}
|
||||
if (name.length() > 0) {
|
||||
drawPointText(req, rc, tag, value, px, py, name);
|
||||
drawPointText(req, rc, tag, value, px, py, name, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -208,26 +208,128 @@ void drawWrappedText(SkCanvas* cv, TextDrawInfo* text, float textSize, SkPaint&
|
|||
}
|
||||
}
|
||||
|
||||
bool calculatePathToRotate(TextDrawInfo* p) {
|
||||
// TODO rotate bounds for shields?
|
||||
if (!p->drawOnPath || p->path == NULL) {
|
||||
return true;
|
||||
}
|
||||
uint len = p->path->countPoints();
|
||||
bool inverse = false;
|
||||
float roadLength = 0;
|
||||
SkPoint points[len];
|
||||
p->path->getPoints(points, len);
|
||||
// calculate vector of the road (px, py)
|
||||
float px = 0;
|
||||
float py = 0;
|
||||
// TODO path outside (big zoom)
|
||||
for (uint i = 0; i < len; i++) {
|
||||
if (i > 0) {
|
||||
roadLength += 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));
|
||||
px += points[i].fX - points[i - 1].fX;
|
||||
py += points[i].fY - points[i - 1].fY;
|
||||
}
|
||||
|
||||
}
|
||||
if (p->bounds.width() >= roadLength) {
|
||||
return false;
|
||||
}
|
||||
float scale = 0.5f;
|
||||
float plen = std::sqrt(px * px + py * py);
|
||||
// vector ox,oy orthogonal to px,py to measure height
|
||||
float ox = -py;
|
||||
float oy = px;
|
||||
if(plen > 0) {
|
||||
float rot = std::atan2(py, px) * 180 / M_PI;
|
||||
if (rot < 0) rot += 360;
|
||||
if (rot > 90 && rot < 270) {
|
||||
rot += 180;
|
||||
inverse = true;
|
||||
}
|
||||
p->pathRotate = rot;
|
||||
scale = (1 - p->bounds.width() / plen) / 2;
|
||||
ox *= (p->bounds.height() / plen) / 2;
|
||||
oy *= (p->bounds.height() / plen) / 2;
|
||||
}
|
||||
|
||||
|
||||
p->centerX = points[0].fX + scale * px + ox;
|
||||
p->centerY = points[0].fY + scale * py + oy;
|
||||
p->vOffset = p->textSize / 2 - 1;
|
||||
// TODO ?
|
||||
p->hOffset = 0;
|
||||
|
||||
|
||||
if (inverse) {
|
||||
SkPath* path = new SkPath;
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
if (i == (int)(len - 1)) {
|
||||
path->moveTo(points[i].fX, points[i].fY);
|
||||
} else {
|
||||
path->lineTo(points[i].fX, points[i].fY);
|
||||
}
|
||||
}
|
||||
if (p->path != NULL) {
|
||||
delete p->path;
|
||||
}
|
||||
p->path = path;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void drawTestBox(SkCanvas* cv, TextDrawInfo* text, SkPaint* paintIcon, SkPaint* paintText)
|
||||
{
|
||||
cv->save();
|
||||
cv->translate(text->bounds.centerX(),text->bounds.centerY());
|
||||
cv->rotate(text->pathRotate);
|
||||
SkRect r = SkRect::MakeLTRB(-text->bounds.width()/2, -text->bounds.height()/2,
|
||||
text->bounds.width()/2, text->bounds.height()/2);
|
||||
cv->drawRect(r, *paintIcon);
|
||||
if (paintText != NULL) {
|
||||
cv->drawText(text->text.data(), text->text.length(), r.centerX(), r.centerY(),
|
||||
*paintText);
|
||||
}
|
||||
cv->restore();
|
||||
}
|
||||
|
||||
bool intersect(TextDrawInfo* t, TextDrawInfo* s)
|
||||
{
|
||||
// TODO rotation
|
||||
return t->bounds.intersect(s->bounds);
|
||||
}
|
||||
|
||||
std::vector<TextDrawInfo*> search;
|
||||
bool findTextIntersection(SkCanvas* cv, RenderingContext* rc, quad_tree<TextDrawInfo*>& boundIntersections, TextDrawInfo* text,
|
||||
SkPaint* paintText, SkPaint* paintIcon) {
|
||||
// TODO direction of path
|
||||
//bool horizontalWayDisplay = (text->pathRotate > 45 && text->pathRotate < 135)
|
||||
// || (text->pathRotate > 225 && text->pathRotate < 315);
|
||||
paintText->measureText(text->text.c_str(), text->text.length(), &text->bounds);
|
||||
// make wider
|
||||
text->bounds.inset(-getDensityValue(rc, 3), -getDensityValue(rc, 10));
|
||||
text->bounds.offset(text->centerX, text->centerY);
|
||||
text->bounds.offset(-text->bounds.width()/2, 0);
|
||||
|
||||
bool display = calculatePathToRotate(text);
|
||||
if (!display) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!text->drawOnPath) {
|
||||
text->bounds.offset(text->centerX, text->centerY);
|
||||
// shift to match alignment
|
||||
text->bounds.offset(-text->bounds.width()/2, 0);
|
||||
} else {
|
||||
text->bounds.offset(text->centerX - text->bounds.width()/2, text->centerY - text->bounds.height()/2);
|
||||
}
|
||||
|
||||
|
||||
SkRect boundsSearch = text->bounds;
|
||||
float v = -getDensityValue(rc, std::max(5.0f, text->minDistance));
|
||||
boundsSearch.inset(v, v);
|
||||
|
||||
//TODO remove
|
||||
// cv->drawRect(text->bounds, *paintIcon);
|
||||
drawTestBox(cv, text, paintIcon, paintText);
|
||||
boundIntersections.query_in_box(boundsSearch, search);
|
||||
for (uint i = 0; i < search.size(); i++) {
|
||||
TextDrawInfo* t = search.at(i);
|
||||
if (text->bounds.intersect(t->bounds)) {
|
||||
if (intersect(text, t)) {
|
||||
return true;
|
||||
} else if (boundsSearch.intersect(t->bounds) && t->text == text->text) {
|
||||
return true;
|
||||
|
@ -247,7 +349,7 @@ SkTypeface* serif = SkTypeface::CreateFromName("Droid Serif", SkTypeface::kNorma
|
|||
void drawTextOverCanvas(RenderingContext* rc, SkCanvas* cv) {
|
||||
SkRect r = SkRect::MakeLTRB(0, 0, rc->width, rc->height);
|
||||
r.inset(-100, -100);
|
||||
quad_tree<TextDrawInfo*> boundsIntersect(r, 5, 0.7);
|
||||
quad_tree<TextDrawInfo*> boundsIntersect(r, 4, 0.6);
|
||||
|
||||
SkPaint paintIcon;
|
||||
paintIcon.setStyle(SkPaint::kStroke_Style);
|
||||
|
@ -287,20 +389,20 @@ void drawTextOverCanvas(RenderingContext* rc, SkCanvas* cv) {
|
|||
// calculate if there is intersection
|
||||
bool intersects = findTextIntersection(cv, rc, boundsIntersect, text, &paintText, &paintIcon);
|
||||
if (!intersects) {
|
||||
if (text->drawOnPath != NULL) {
|
||||
if (text->drawOnPath && text->path != NULL) {
|
||||
if (text->textShadow > 0) {
|
||||
paintText.setColor(WHITE_COLOR);
|
||||
paintText.setStyle(SkPaint::kStroke_Style);
|
||||
paintText.setStrokeWidth(2 + text->textShadow);
|
||||
cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->drawOnPath, 0,
|
||||
cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->path, text->hOffset,
|
||||
text->vOffset, paintText);
|
||||
// reset
|
||||
paintText.setStyle(SkPaint::kFill_Style);
|
||||
paintText.setStrokeWidth(2);
|
||||
paintText.setColor(text->textColor);
|
||||
}
|
||||
cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->drawOnPath, 0, text->vOffset,
|
||||
paintText);
|
||||
cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->path, text->hOffset,
|
||||
text->vOffset, paintText);
|
||||
} else {
|
||||
if (text->shieldRes.length() > 0) {
|
||||
SkBitmap* ico = getCachedBitmap(rc, text->shieldRes);
|
||||
|
|
Binary file not shown.
|
@ -448,6 +448,9 @@ 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;
|
||||
}
|
||||
if (checkWhetherInterrupted()) {
|
||||
currentRenderingContext = null;
|
||||
return;
|
||||
|
@ -488,7 +491,10 @@ public class MapRenderRepositories {
|
|||
Toast.makeText(context, R.string.rendering_out_of_memory, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
} finally {
|
||||
if(currentRenderingContext != null) {
|
||||
currentRenderingContext.ended = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ import android.graphics.Paint.Align;
|
|||
import android.graphics.Paint.Cap;
|
||||
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;
|
||||
|
@ -162,6 +165,8 @@ public class OsmandRenderer {
|
|||
int shadowLevelMax = 0;
|
||||
|
||||
String renderingDebugInfo;
|
||||
|
||||
boolean ended = false;
|
||||
}
|
||||
|
||||
public OsmandRenderer(Context context) {
|
||||
|
@ -224,7 +229,7 @@ public class OsmandRenderer {
|
|||
|
||||
|
||||
public Bitmap generateNewBitmap(RenderingContext rc, List<BinaryMapDataObject> objects, Bitmap bmp, boolean useEnglishNames,
|
||||
RenderingRuleSearchRequest render, List<IMapDownloaderCallback> notifyList, int defaultColor, boolean nativeRendering) {
|
||||
RenderingRuleSearchRequest render, final List<IMapDownloaderCallback> notifyList, int defaultColor, boolean nativeRendering) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (objects != null && !objects.isEmpty() && rc.width > 0 && rc.height > 0) {
|
||||
|
@ -309,7 +314,12 @@ public class OsmandRenderer {
|
|||
} else {
|
||||
BinaryMapDataObject[] array = objects.toArray(new BinaryMapDataObject[objects.size()]);
|
||||
try {
|
||||
if(Looper.getMainLooper() != null){
|
||||
final Handler h = new Handler(Looper.getMainLooper());
|
||||
notifyListenersWithDelay(rc, notifyList, h);
|
||||
}
|
||||
String res = NativeOsmandLibrary.generateRendering(rc, array, bmp, useEnglishNames, render, defaultColor);
|
||||
rc.ended = true;
|
||||
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$
|
||||
|
@ -323,6 +333,18 @@ public class OsmandRenderer {
|
|||
return bmp;
|
||||
}
|
||||
|
||||
private void notifyListenersWithDelay(final RenderingContext rc, final List<IMapDownloaderCallback> notifyList, final Handler h) {
|
||||
h.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(!rc.ended) {
|
||||
notifyListeners(notifyList);
|
||||
notifyListenersWithDelay(rc, notifyList, h);
|
||||
}
|
||||
}
|
||||
}, 700);
|
||||
}
|
||||
|
||||
private void drawIconsOverCanvas(RenderingContext rc, Canvas cv) {
|
||||
int skewConstant = (int) getDensityValue(rc, 16);
|
||||
int iconsW = rc.width / skewConstant;
|
||||
|
|
Loading…
Reference in a new issue