diff --git a/yg/glyph_layout.cpp b/yg/glyph_layout.cpp index b78e481e2a..bf75eb6480 100644 --- a/yg/glyph_layout.cpp +++ b/yg/glyph_layout.cpp @@ -68,7 +68,7 @@ namespace yg m_lastVisible(visText.size()), m_pivot(pt) { - m2::RectD limitRect; + m2::RectD boundRect; m2::PointD curPt(0, 0); bool isFirst = true; @@ -81,16 +81,16 @@ namespace yg if (isFirst) { - limitRect = m2::RectD(m.m_xOffset, + boundRect = m2::RectD(m.m_xOffset, -m.m_yOffset, m.m_xOffset, -m.m_yOffset); isFirst = false; } else - limitRect.Add(m2::PointD(m.m_xOffset + curPt.x, -m.m_yOffset + curPt.y)); + boundRect.Add(m2::PointD(m.m_xOffset + curPt.x, -m.m_yOffset + curPt.y)); - limitRect.Add(m2::PointD(m.m_xOffset + m.m_width, + boundRect.Add(m2::PointD(m.m_xOffset + m.m_width, -(m.m_yOffset + m.m_height)) + curPt); GlyphLayoutElem elem; @@ -103,29 +103,30 @@ namespace yg curPt += m2::PointD(m.m_xAdvance, m.m_yAdvance); } - limitRect.Inflate(2, 2); + boundRect.Inflate(2, 2); - m2::PointD ptOffs(-limitRect.SizeX() / 2 - limitRect.minX(), - -limitRect.SizeY() / 2 - limitRect.minY()); + m2::PointD ptOffs(-boundRect.SizeX() / 2 - boundRect.minX(), + -boundRect.SizeY() / 2 - boundRect.minY()); /// adjusting according to position if (pos & EPosLeft) - ptOffs += m2::PointD(-limitRect.SizeX() / 2, 0); + ptOffs += m2::PointD(-boundRect.SizeX() / 2, 0); + if (pos & EPosRight) - ptOffs += m2::PointD(limitRect.SizeX() / 2, 0); + ptOffs += m2::PointD(boundRect.SizeX() / 2, 0); if (pos & EPosAbove) - ptOffs += m2::PointD(0, -limitRect.SizeY() / 2); + ptOffs += m2::PointD(0, -boundRect.SizeY() / 2); if (pos & EPosUnder) - ptOffs += m2::PointD(0, limitRect.SizeY() / 2); - - m_limitRect = m2::AARectD(limitRect); + ptOffs += m2::PointD(0, boundRect.SizeY() / 2); for (unsigned i = 0; i < m_entries.size(); ++i) m_entries[i].m_pt += ptOffs; - m_limitRect.Offset(ptOffs); + boundRect.Offset(ptOffs); + + m_boundRects.push_back(boundRect); } GlyphLayout::GlyphLayout(GlyphLayout const & src, @@ -137,9 +138,9 @@ namespace yg m_pos(src.m_pos), m_fontDesc(src.m_fontDesc), m_metrics(src.m_metrics), - m_limitRect(m2::RectD(0, 0, 0, 0)), m_pivot(0, 0) { + m_boundRects.push_back(m2::AARectD(m2::RectD(0, 0, 0, 0))); m_fullLength = (m2::PointD(src.m_fullLength, 0) * m).Length(m2::PointD(0, 0) * m); m_pathOffset = (m2::PointD(src.m_pathOffset, 0) * m).Length(m2::PointD(0, 0) * m); recalcAlongPath(); @@ -161,9 +162,9 @@ namespace yg m_visText(visText), m_pos(pos), m_fontDesc(fontDesc), - m_limitRect(m2::RectD(0, 0, 0, 0)), m_pivot(0, 0) { + m_boundRects.push_back(m2::AARectD(m2::RectD(0, 0, 0, 0))); for (size_t i = 0; i < m_visText.size(); ++i) m_metrics.push_back(glyphCache->getGlyphMetrics(GlyphKey(visText[i], m_fontDesc.m_size, m_fontDesc.m_isMasked, yg::Color(0, 0, 0, 0)))); recalcAlongPath(); @@ -317,17 +318,10 @@ namespace yg for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) m_entries[i].m_pt -= m_pivot; - computeMinLimitRect(); - -// recalcPivot(); + computeBoundRects(); } - void GlyphLayout::recalcPivot() - { - - } - - void GlyphLayout::computeMinLimitRect() + void GlyphLayout::computeBoundRects() { map rects; @@ -337,58 +331,39 @@ namespace yg { map::iterator it = rects.find(m_entries[i].m_angle.val()); - if (it == rects.end()) - { - m2::AARectD symRectAA( - m_entries[i].m_pt.Move(m_metrics[i].m_height, -m_entries[i].m_angle.cos(), m_entries[i].m_angle.sin()), //< moving by angle = m_entries[i].m_angle - math::pi / 2 - m_entries[i].m_angle, - m2::RectD(m_metrics[i].m_xOffset, - m_metrics[i].m_yOffset, - m_metrics[i].m_xOffset + m_metrics[i].m_width, - m_metrics[i].m_yOffset + m_metrics[i].m_height - )); - - rects[m_entries[i].m_angle.val()] = symRectAA; - } - } - } - - for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) - { - if (m_metrics[i].m_width != 0) - { m2::AARectD symRectAA( m_entries[i].m_pt.Move(m_metrics[i].m_height, -m_entries[i].m_angle.cos(), m_entries[i].m_angle.sin()), //< moving by angle = m_entries[i].m_angle - math::pi / 2 m_entries[i].m_angle, m2::RectD(m_metrics[i].m_xOffset, m_metrics[i].m_yOffset, m_metrics[i].m_xOffset + m_metrics[i].m_width, - m_metrics[i].m_yOffset + m_metrics[i].m_height)); + m_metrics[i].m_yOffset + m_metrics[i].m_height + )); - for (map::iterator it = rects.begin(); it != rects.end(); ++it) - it->second.Add(symRectAA); + if (it == rects.end()) + rects[m_entries[i].m_angle.val()] = symRectAA; + else + rects[m_entries[i].m_angle.val()].Add(symRectAA); } } - double square = numeric_limits::max(); + m_boundRects.clear(); - for (map::iterator it = rects.begin(); it != rects.end(); ++it) + for (map::const_iterator it = rects.begin(); it != rects.end(); ++it) { - m2::RectD r = it->second.GetLocalRect(); - if (square > r.SizeX() * r.SizeY()) - { - m_limitRect = it->second; - square = r.SizeX() * r.SizeY(); - } + m2::AARectD r(it->second); + m2::PointD zero = r.zero(); + zero = r.ConvertFrom(zero); + + double dx = zero.x - floor(zero.x); + double dy = zero.y - floor(zero.y); + + r.Offset(m2::PointD(-dx, -dy)); + + r.Offset(m_pivot); + + m_boundRects.push_back(r); } - - m2::PointD zero = m_limitRect.zero(); - zero = m_limitRect.ConvertFrom(zero); - - double dx = zero.x - floor(zero.x); - double dy = zero.y - floor(zero.y); - - m_limitRect.Offset(m2::PointD(-dx, -dy)); } size_t GlyphLayout::firstVisible() const @@ -411,9 +386,9 @@ namespace yg return m_metrics; } - m2::AARectD const GlyphLayout::limitRect() const + vector const & GlyphLayout::boundRects() const { - return m2::Offset(m_limitRect, pivot()); + return m_boundRects; } m2::PointD const & GlyphLayout::pivot() const @@ -423,6 +398,9 @@ namespace yg void GlyphLayout::setPivot(m2::PointD const & pivot) { + for (unsigned i = 0; i < m_boundRects.size(); ++i) + m_boundRects[i].Offset(pivot - m_pivot); + m_pivot = pivot; } } diff --git a/yg/glyph_layout.hpp b/yg/glyph_layout.hpp index 275c701bf8..81b3ef07ca 100644 --- a/yg/glyph_layout.hpp +++ b/yg/glyph_layout.hpp @@ -50,12 +50,12 @@ namespace yg vector m_metrics; vector m_entries; - m2::AARectD m_limitRect; + vector m_boundRects; m2::PointD m_pivot; double getKerning(GlyphLayoutElem const & prevElem, GlyphMetrics const & prevMetrics, GlyphLayoutElem const & curElem, GlyphMetrics const & curMetrics); - void computeMinLimitRect(); + void computeBoundRects(); void recalcPivot(); void recalcAlongPath(); @@ -88,7 +88,7 @@ namespace yg vector const & entries() const; vector const & metrics() const; - m2::AARectD const limitRect() const; + vector const & boundRects() const; m2::PointD const & pivot() const; diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp index 1f03365244..417551092b 100644 --- a/yg/info_layer.cpp +++ b/yg/info_layer.cpp @@ -14,29 +14,10 @@ namespace yg bool betterOverlayElement(shared_ptr const & l, shared_ptr const & r) { + /// "frozen" object shouldn't be popped out. if (r->isFrozen()) return false; - vector const & lr = l->boundRects(); - vector const & rr = r->boundRects(); - - bool isIntersect = false; - - for (vector::const_iterator lit = lr.begin(); lit != lr.end(); ++lit) - { - for (vector::const_iterator rit = rr.begin(); rit != rr.end(); ++rit) - { - isIntersect = lit->IsIntersect(*rit); - if (isIntersect) - break; - } - if (isIntersect) - break; - } - - if (!isIntersect) - return true; - /// for the composite elements, collected in OverlayRenderer to replace the part elements return l->visualRank() >= r->visualRank(); } @@ -117,9 +98,45 @@ namespace yg m_tree.Add(oe); } + struct DoPreciseIntersect + { + shared_ptr m_oe; + bool * m_isIntersect; + + DoPreciseIntersect(shared_ptr const & oe, bool * isIntersect) + : m_oe(oe), + m_isIntersect(isIntersect) + {} + + void operator()(shared_ptr const & e) + { + if (*m_isIntersect) + return; + + vector const & lr = m_oe->boundRects(); + vector const & rr = e->boundRects(); + + for (vector::const_iterator lit = lr.begin(); lit != lr.end(); ++lit) + { + for (vector::const_iterator rit = rr.begin(); rit != rr.end(); ++rit) + { + *m_isIntersect = lit->IsIntersect(*rit); + if (*m_isIntersect) + return; + } + } + } + }; + void InfoLayer::replaceOverlayElement(shared_ptr const & oe) { - m_tree.ReplaceIf(oe, &betterOverlayElement); + bool isIntersect = false; + DoPreciseIntersect fn(oe, &isIntersect); + m_tree.ForEachInRect(oe->roughBoundRect(), fn); + if (isIntersect) + m_tree.ReplaceIf(oe, &betterOverlayElement); + else + m_tree.Add(oe); } void InfoLayer::processOverlayElement(shared_ptr const & oe, math::Matrix const & m) @@ -132,10 +149,11 @@ namespace yg void InfoLayer::processOverlayElement(shared_ptr const & oe) { - if (m_couldOverlap) - addOverlayElement(oe); - else - replaceOverlayElement(oe); + if (oe->isVisible()) + if (m_couldOverlap) + addOverlayElement(oe); + else + replaceOverlayElement(oe); } void InfoLayer::merge(InfoLayer const & layer, math::Matrix const & m) diff --git a/yg/overlay_element.cpp b/yg/overlay_element.cpp index 21eae9e63b..20f1785673 100644 --- a/yg/overlay_element.cpp +++ b/yg/overlay_element.cpp @@ -16,6 +16,7 @@ namespace yg m_depth(p.m_depth), m_isNeedRedraw(true), m_isFrozen(false), + m_isVisible(true), m_isDirtyRect(true), m_isDirtyRoughRect(true) {} @@ -102,6 +103,16 @@ namespace yg m_isNeedRedraw = flag; } + bool OverlayElement::isVisible() const + { + return m_isVisible; + } + + void OverlayElement::setIsVisible(bool flag) + { + m_isVisible = flag; + } + bool OverlayElement::isDirtyRect() const { return m_isDirtyRect; diff --git a/yg/overlay_element.hpp b/yg/overlay_element.hpp index 8bf62ec943..12a3baca64 100644 --- a/yg/overlay_element.hpp +++ b/yg/overlay_element.hpp @@ -25,6 +25,7 @@ namespace yg bool m_isNeedRedraw; bool m_isFrozen; + bool m_isVisible; mutable bool m_isDirtyRect; mutable bool m_isDirtyRoughRect; @@ -79,6 +80,9 @@ namespace yg bool isDirtyRect() const; void setIsDirtyRect(bool flag) const; + bool isVisible() const; + void setIsVisible(bool flag); + m2::RectD const & roughBoundRect() const; virtual void offset(m2::PointD const & offs); diff --git a/yg/path_text_element.cpp b/yg/path_text_element.cpp index 2d8985e165..c8d9f5b6b0 100644 --- a/yg/path_text_element.cpp +++ b/yg/path_text_element.cpp @@ -16,6 +16,7 @@ namespace yg p.m_position) { setPivot(m_glyphLayout.pivot()); + setIsVisible((m_glyphLayout.firstVisible() == 0) && (m_glyphLayout.lastVisible() == visText().size())); } PathTextElement::PathTextElement(PathTextElement const & src, math::Matrix const & m) @@ -23,21 +24,17 @@ namespace yg m_glyphLayout(src.m_glyphLayout, m) { setPivot(m_glyphLayout.pivot()); - } - - m2::AARectD const PathTextElement::boundRect() const - { - // return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(2, 2)); - return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(10, 2)); - // return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(40, 2)); //< to create more sparse street names structure + setIsVisible((m_glyphLayout.firstVisible() == 0) && (m_glyphLayout.lastVisible() == visText().size())); } vector const & PathTextElement::boundRects() const { if (isDirtyRect()) { - m_boundRects.clear(); - m_boundRects.push_back(boundRect()); + m_boundRects = m_glyphLayout.boundRects(); + for (unsigned i = 0; i < m_boundRects.size(); ++i) + m_boundRects[i] = m2::Inflate(m_boundRects[i], m2::PointD(10, 2)); + // m_boundRects[i].m2::Inflate(m2::PointD(40, 2)); //< to create more sparse street names structure setIsDirtyRect(false); } diff --git a/yg/path_text_element.hpp b/yg/path_text_element.hpp index cafc76df24..ecf0822893 100644 --- a/yg/path_text_element.hpp +++ b/yg/path_text_element.hpp @@ -10,8 +10,6 @@ namespace yg GlyphLayout m_glyphLayout; - m2::AARectD const boundRect() const; - public: struct Params : TextElement::Params diff --git a/yg/straight_text_element.cpp b/yg/straight_text_element.cpp index 2bbf537f3b..dbb8c25df4 100644 --- a/yg/straight_text_element.cpp +++ b/yg/straight_text_element.cpp @@ -102,7 +102,7 @@ namespace yg for (unsigned i = 0; i < res.size(); ++i) { m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_fontDesc, m2::PointD(0, 0), res[i], yg::EPosCenter)); - m2::RectD r = m_glyphLayouts.back().limitRect().GetGlobalRect(); + m2::RectD r = m_glyphLayouts.back().boundRects().back().GetGlobalRect(); allElemWidth = max(r.SizeX(), allElemWidth); allElemHeight += r.SizeY(); } @@ -113,7 +113,7 @@ namespace yg for (unsigned i = 0; i < res.size(); ++i) { - double elemSize = m_glyphLayouts[i].limitRect().GetGlobalRect().SizeY(); + double elemSize = m_glyphLayouts[i].boundRects().back().GetGlobalRect().SizeY(); m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, -curShift + elemSize / 2)); curShift -= elemSize; } @@ -169,7 +169,9 @@ namespace yg m_boundRects.clear(); for (size_t i = 0; i < m_glyphLayouts.size(); ++i) - m_boundRects.push_back(m_glyphLayouts[i].limitRect()); + copy(m_glyphLayouts[i].boundRects().begin(), + m_glyphLayouts[i].boundRects().end(), + back_inserter(m_boundRects)); setIsDirtyRect(false); }