Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorr.kuznetsov <r.kuznetsov@corp.mail.ru>2016-01-29 14:06:10 +0300
committerSergey Yershov <yershov@corp.mail.ru>2016-03-23 16:20:41 +0300
commitf4de5841f7bbfa1773ecd824d366a8bea49515a9 (patch)
tree16ee18c3f36b549e15fbf25c3e2cdfb2b5628b00
parent2317f55b5a9460654f0916f6b85d7fa23837d3be (diff)
Improved displacement algorithm and overlays rendering
-rw-r--r--drape/color.hpp1
-rw-r--r--drape/debug_rect_renderer.cpp4
-rw-r--r--drape/debug_rect_renderer.hpp2
-rw-r--r--drape/overlay_handle.cpp33
-rw-r--r--drape/overlay_handle.hpp19
-rw-r--r--drape/overlay_tree.cpp217
-rw-r--r--drape/overlay_tree.hpp38
-rw-r--r--drape/render_bucket.cpp3
-rw-r--r--drape_frontend/apply_feature_functors.cpp13
-rw-r--r--drape_frontend/area_shape.hpp2
-rw-r--r--drape_frontend/backend_renderer.cpp30
-rw-r--r--drape_frontend/backend_renderer.hpp4
-rw-r--r--drape_frontend/circle_shape.cpp2
-rw-r--r--drape_frontend/circle_shape.hpp1
-rwxr-xr-xdrape_frontend/drape_frontend.pro2
-rw-r--r--drape_frontend/engine_context.cpp17
-rw-r--r--drape_frontend/engine_context.hpp2
-rwxr-xr-xdrape_frontend/frontend_renderer.cpp48
-rwxr-xr-xdrape_frontend/frontend_renderer.hpp1
-rw-r--r--drape_frontend/line_shape.hpp1
-rw-r--r--drape_frontend/map_shape.hpp57
-rw-r--r--drape_frontend/message.hpp2
-rw-r--r--drape_frontend/message_subclasses.hpp37
-rw-r--r--drape_frontend/overlay_batcher.cpp43
-rw-r--r--drape_frontend/overlay_batcher.hpp49
-rw-r--r--drape_frontend/path_symbol_shape.hpp1
-rw-r--r--drape_frontend/path_text_shape.cpp61
-rw-r--r--drape_frontend/path_text_shape.hpp5
-rw-r--r--drape_frontend/poi_symbol_shape.cpp1
-rw-r--r--drape_frontend/poi_symbol_shape.hpp2
-rw-r--r--drape_frontend/rule_drawer.cpp49
-rw-r--r--drape_frontend/rule_drawer.hpp2
-rw-r--r--drape_frontend/shape_view_params.hpp38
-rw-r--r--drape_frontend/stylist.cpp8
-rw-r--r--drape_frontend/stylist.hpp2
-rw-r--r--drape_frontend/text_handle.cpp11
-rw-r--r--drape_frontend/text_handle.hpp4
-rw-r--r--drape_frontend/text_layout.cpp26
-rw-r--r--drape_frontend/text_layout.hpp12
-rw-r--r--drape_frontend/text_shape.cpp19
-rw-r--r--drape_frontend/text_shape.hpp5
-rw-r--r--drape_head/testing_engine.cpp2
-rw-r--r--geometry/screenbase.cpp12
-rw-r--r--geometry/screenbase.hpp2
44 files changed, 594 insertions, 296 deletions
diff --git a/drape/color.hpp b/drape/color.hpp
index 7903b1e9c0..3bdd95a911 100644
--- a/drape/color.hpp
+++ b/drape/color.hpp
@@ -28,6 +28,7 @@ struct Color
static Color Black() { return Color(0, 0, 0, 255); }
static Color White() { return Color(255, 255, 255, 255); }
static Color Red() { return Color(255, 0, 0, 255); }
+ static Color Green() { return Color(0, 255, 0, 255); }
static Color Transparent() { return Color(0, 0, 0, 0); }
private:
diff --git a/drape/debug_rect_renderer.cpp b/drape/debug_rect_renderer.cpp
index 5f422600ad..2aa547bdb8 100644
--- a/drape/debug_rect_renderer.cpp
+++ b/drape/debug_rect_renderer.cpp
@@ -85,7 +85,7 @@ void DebugRectRenderer::SetEnabled(bool enabled)
m_isEnabled = enabled;
}
-void DebugRectRenderer::DrawRect(ScreenBase const & screen, m2::RectF const & rect) const
+void DebugRectRenderer::DrawRect(ScreenBase const & screen, m2::RectF const & rect, dp::Color const & color) const
{
if (!m_isEnabled)
return;
@@ -110,7 +110,7 @@ void DebugRectRenderer::DrawRect(ScreenBase const & screen, m2::RectF const & re
int8_t const location = m_program->GetUniformLocation("u_color");
if (location >= 0)
- GLFunctions::glUniformValuef(location, 1.0, 0.0, 0.0, 1.0);
+ GLFunctions::glUniformValuef(location, color.GetRedF(), color.GetGreenF(), color.GetBlueF(), color.GetAlfaF());
GLFunctions::glDrawArrays(gl_const::GLLineStrip, 0, vertices.size());
diff --git a/drape/debug_rect_renderer.hpp b/drape/debug_rect_renderer.hpp
index 7c64749e27..19e0ef5820 100644
--- a/drape/debug_rect_renderer.hpp
+++ b/drape/debug_rect_renderer.hpp
@@ -22,7 +22,7 @@ public:
bool IsEnabled() const;
void SetEnabled(bool enabled);
- void DrawRect(ScreenBase const & screen, m2::RectF const & rect) const;
+ void DrawRect(ScreenBase const & screen, m2::RectF const & rect, dp::Color const & color) const;
#ifdef COLLECT_DISPLACEMENT_INFO
void DrawArrow(ScreenBase const & screen, OverlayTree::DisplacementData const & data) const;
diff --git a/drape/overlay_handle.cpp b/drape/overlay_handle.cpp
index c7cc6e4926..d656048c6e 100644
--- a/drape/overlay_handle.cpp
+++ b/drape/overlay_handle.cpp
@@ -2,11 +2,12 @@
#include "base/macros.hpp"
+#include "base/internal/message.hpp"
+#include "base/logging.hpp"
+
namespace dp
{
-double const k3dAdditionalExtention = 2.0;
-
struct OverlayHandle::OffsetNodeFinder
{
public:
@@ -44,8 +45,6 @@ bool OverlayHandle::IsVisible() const
void OverlayHandle::SetIsVisible(bool isVisible)
{
m_isVisible = isVisible;
- if (m_isVisible && IsMinVisibilityTimeUp())
- m_visibilityTimestamp = steady_clock::now();
}
bool OverlayHandle::IsBillboard() const
@@ -143,8 +142,6 @@ m2::RectD OverlayHandle::GetExtendedPixelRect(ScreenBase const & screen) const
{
m2::RectD rect = GetPixelRect(screen, screen.isPerspective());
rect.Inflate(m_extendingSize, m_extendingSize);
- if (Enable3dExtention() && screen.isPerspective())
- rect.Scale(k3dAdditionalExtention);
return rect;
}
@@ -152,11 +149,7 @@ void OverlayHandle::GetExtendedPixelShape(ScreenBase const & screen, Rects & rec
{
GetPixelShape(screen, rects, screen.isPerspective());
for (auto & rect : rects)
- {
rect.Inflate(m_extendingSize, m_extendingSize);
- if (Enable3dExtention() && screen.isPerspective())
- rect.Scale(k3dAdditionalExtention);
- }
}
m2::RectD OverlayHandle::GetPerspectiveRect(m2::RectD const & pixelRect, ScreenBase const & screen) const
@@ -187,13 +180,6 @@ m2::RectD OverlayHandle::GetPixelRectPerspective(ScreenBase const & screen) cons
return GetPerspectiveRect(GetPixelRect(screen, false), screen);
}
-bool OverlayHandle::IsMinVisibilityTimeUp() const
-{
- uint32_t const kMinVisibilityTimeMs = 500;
- uint32_t const t = duration_cast<milliseconds>(steady_clock::now() - m_visibilityTimestamp).count();
- return t > kMinVisibilityTimeMs;
-}
-
uint64_t OverlayHandle::GetPriorityInFollowingMode() const
{
return GetPriority();
@@ -203,10 +189,14 @@ uint64_t OverlayHandle::GetPriorityInFollowingMode() const
SquareHandle::SquareHandle(FeatureID const & id, dp::Anchor anchor,
m2::PointD const & gbPivot, m2::PointD const & pxSize,
uint64_t priority,
+ string const & debugStr,
bool isBillboard)
: TBase(id, anchor, priority, isBillboard)
, m_gbPivot(gbPivot)
, m_pxHalfSize(pxSize.x / 2.0, pxSize.y / 2.0)
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ , m_debugStr(debugStr)
+#endif
{}
m2::RectD SquareHandle::GetPixelRect(ScreenBase const & screen, bool perspective) const
@@ -237,6 +227,15 @@ void SquareHandle::GetPixelShape(ScreenBase const & screen, Rects & rects, bool
rects.emplace_back(GetPixelRect(screen, perspective));
}
+#ifdef DEBUG_OVERLAYS_OUTPUT
+string SquareHandle::GetOverlayDebugInfo()
+{
+ ostringstream out;
+ out << "POI Priority(" << GetPriority() << ") " << GetFeatureID().m_index << " " << m_debugStr;
+ return out.str();
+}
+#endif
+
uint64_t CalculateOverlayPriority(int minZoomLevel, uint8_t rank, float depth)
{
// Overlay priority consider the following:
diff --git a/drape/overlay_handle.hpp b/drape/overlay_handle.hpp
index 0da93b7e5f..0553891a60 100644
--- a/drape/overlay_handle.hpp
+++ b/drape/overlay_handle.hpp
@@ -14,11 +14,11 @@
#include "base/buffer_vector.hpp"
-#include "std/chrono.hpp"
-
namespace dp
{
+//#define DEBUG_OVERLAYS_OUTPUT
+
enum OverlayRank
{
OverlayRank0 = 0,
@@ -90,7 +90,9 @@ public:
int GetOverlayRank() const { return m_overlayRank; }
void SetOverlayRank(int overlayRank) { m_overlayRank = overlayRank; }
- bool IsMinVisibilityTimeUp() const;
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ virtual string GetOverlayDebugInfo() { return ""; }
+#endif
protected:
FeatureID const m_id;
@@ -101,8 +103,6 @@ protected:
double m_extendingSize;
double m_pivotZ;
- steady_clock::time_point m_visibilityTimestamp;
-
typedef pair<BindingInfo, MutateRegion> TOffsetNode;
TOffsetNode const & GetOffsetNode(uint8_t bufferID) const;
@@ -137,14 +137,23 @@ public:
m2::PointD const & gbPivot,
m2::PointD const & pxSize,
uint64_t priority,
+ string const & debugStr,
bool isBillboard = false);
virtual m2::RectD GetPixelRect(ScreenBase const & screen, bool perspective) const override;
virtual void GetPixelShape(ScreenBase const & screen, Rects & rects, bool perspective) const override;
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ virtual string GetOverlayDebugInfo() override;
+#endif
+
private:
m2::PointD m_gbPivot;
m2::PointD m_pxHalfSize;
+
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ string m_debugStr;
+#endif
};
uint64_t CalculateOverlayPriority(int minZoomLevel, uint8_t rank, float depth);
diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp
index 599d3ab7a0..b27bc4074c 100644
--- a/drape/overlay_tree.cpp
+++ b/drape/overlay_tree.cpp
@@ -8,9 +8,7 @@ namespace dp
int const kFrameUpdarePeriod = 10;
int const kFrameUpdarePeriodIn3d = 30;
-int const kAverageHandlesCount[dp::OverlayRanksCount] = { 300, 200, 100 };
-
-using TOverlayContainer = buffer_vector<detail::OverlayInfo, 8>;
+int const kAverageHandlesCount[dp::OverlayRanksCount] = { 300, 200, 50 };
namespace
{
@@ -18,16 +16,20 @@ namespace
class HandleComparator
{
public:
- HandleComparator(bool followingMode) : m_followingMode(followingMode) {}
+ HandleComparator(bool enableMask, bool followingMode)
+ : m_followingMode(followingMode)
+ , m_enableMask(enableMask)
+ {}
bool operator()(ref_ptr<OverlayHandle> const & l, ref_ptr<OverlayHandle> const & r) const
- {
+ {
return IsGreater(l, r);
}
bool IsGreater(ref_ptr<OverlayHandle> const & l, ref_ptr<OverlayHandle> const & r) const
{
- uint64_t const mask = l->GetPriorityMask() & r->GetPriorityMask();
+ uint64_t const mask = m_enableMask ? l->GetPriorityMask() & r->GetPriorityMask() :
+ dp::kPriorityMaskAll;
uint64_t const priorityLeft = (m_followingMode ? l->GetPriorityInFollowingMode() :
l->GetPriority()) & mask;
uint64_t const priorityRight = (m_followingMode ? r->GetPriorityInFollowingMode() :
@@ -39,6 +41,7 @@ public:
{
auto const & hashLeft = l->GetFeatureID();
auto const & hashRight = r->GetFeatureID();
+
if (hashLeft < hashRight)
return true;
@@ -51,6 +54,7 @@ public:
private:
bool m_followingMode;
+ bool m_enableMask;
};
} // namespace
@@ -101,20 +105,34 @@ void OverlayTree::Add(ref_ptr<OverlayHandle> handle)
ASSERT(IsNeedUpdate(), ());
ScreenBase const & modelView = GetModelView();
- bool const is3dMode = modelView.isPerspective();
handle->SetIsVisible(false);
if (!handle->Update(modelView))
return;
+ // Clip handles which are out of screen.
+ double const kScreenRectScale = 1.2;
m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView);
-
- if (!modelView.PixelRect().IsIntersect(handle->GetPixelRect(modelView, false)) ||
- (is3dMode && !modelView.PixelRectIn3d().IsIntersect(pixelRect)))
+ if (modelView.isPerspective())
{
- handle->SetIsVisible(false);
- return;
+ m2::RectD screenRect = modelView.PixelRectIn3d();
+ screenRect.Scale(kScreenRectScale);
+ if (!screenRect.IsIntersect(pixelRect) || modelView.IsReverseProjection3d(pixelRect.Center()))
+ {
+ handle->SetIsVisible(false);
+ return;
+ }
+ }
+ else
+ {
+ m2::RectD screenRect = modelView.PixelRect();
+ screenRect.Scale(kScreenRectScale);
+ if (!screenRect.IsIntersect(pixelRect))
+ {
+ handle->SetIsVisible(false);
+ return;
+ }
}
int const rank = handle->GetOverlayRank();
@@ -123,104 +141,122 @@ void OverlayTree::Add(ref_ptr<OverlayHandle> handle)
}
void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle,
- detail::OverlayInfo const & parentOverlay)
+ ref_ptr<OverlayHandle> const & parentOverlay)
{
ASSERT(IsNeedUpdate(), ());
- ScreenBase const & modelView = GetModelView();
- bool const is3dMode = modelView.isPerspective();
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ string str = handle->GetOverlayDebugInfo();
+ if (!str.empty())
+ LOG(LINFO, (str));
+#endif
+ ScreenBase const & modelView = GetModelView();
m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView);
- TOverlayContainer elements;
+ TOverlayContainer rivals;
+ HandleComparator comparator(true /* enableMask */, m_followingMode);
// Find elements that already on OverlayTree and it's pixel rect
// intersect with handle pixel rect ("Intersected elements").
- ForEachInRect(pixelRect, [&] (detail::OverlayInfo const & info)
+ ForEachInRect(pixelRect, [&] (ref_ptr<OverlayHandle> const & h)
{
- bool const isParent = (info == parentOverlay);
- if (!isParent && handle->IsIntersect(modelView, info.m_handle))
- elements.push_back(info);
+ bool const isParent = (h == parentOverlay);
+ if (!isParent && handle->IsIntersect(modelView, h))
+ rivals.push_back(h);
});
- if (handle->IsMinVisibilityTimeUp())
+ // If handle is bound to its parent, parent's handle will be used.
+ ref_ptr<OverlayHandle> handleToCompare = handle;
+ bool const boundToParent = (parentOverlay != nullptr && handle->IsBound());
+ if (boundToParent)
+ handleToCompare = parentOverlay;
+
+ // In this loop we decide which element must be visible.
+ // If input element "handle" more priority than all "Intersected elements"
+ // than we remove all "Intersected elements" and insert input element "handle".
+ // But if some of already inserted elements more priority than we don't insert "handle".
+ for (auto const & rivalHandle : rivals)
{
- bool const boundToParent = (parentOverlay.m_handle != nullptr && handle->IsBound());
-
- // If handle is bound to its parent, parent's handle will be used.
- ref_ptr<OverlayHandle> handleToCompare = handle;
- if (boundToParent)
- handleToCompare = parentOverlay.m_handle;
-
- double const posY = handleToCompare->GetPivot(modelView, is3dMode).y;
- // In this loop we decide which element must be visible.
- // If input element "handle" more priority than all "Intersected elements"
- // than we remove all "Intersected elements" and insert input element "handle".
- // But if some of already inserted elements more priority than we don't insert "handle".
- HandleComparator comparator(m_followingMode);
- for (auto const & info : elements)
+ bool rejectByDepth = false;
+ if (modelView.isPerspective())
{
- bool const pathTextComparation = handle->HasDynamicAttributes() || info.m_handle->HasDynamicAttributes();
- bool const rejectByDepth = is3dMode ? !pathTextComparation &&
- posY > info.m_handle->GetPivot(modelView, is3dMode).y
- : false;
- bool const rejectByTime = !info.m_handle->IsMinVisibilityTimeUp();
- if (rejectByDepth || rejectByTime || comparator.IsGreater(info.m_handle, handleToCompare))
+ bool const pathTextComparation = handle->HasDynamicAttributes() || rivalHandle->HasDynamicAttributes();
+ rejectByDepth = !pathTextComparation &&
+ handleToCompare->GetPivot(modelView, true).y > rivalHandle->GetPivot(modelView, true).y;
+ }
+
+ if (rejectByDepth || comparator.IsGreater(rivalHandle, handleToCompare))
+ {
+ // Handle is displaced and bound to its parent, parent will be displaced too.
+ if (boundToParent)
{
- // Handle is displaced and bound to its parent, parent will be displaced too.
- if (boundToParent)
- {
- Erase(parentOverlay);
+ Erase(parentOverlay);
- #ifdef COLLECT_DISPLACEMENT_INFO
- m_displacementInfo.emplace_back(DisplacementData(handle->GetPixelRect(modelView, is3dMode).Center(),
- parentOverlay.m_handle->GetPixelRect(modelView, is3dMode).Center(),
- dp::Color(0, 255, 0, 255)));
- #endif
- }
+ #ifdef DEBUG_OVERLAYS_OUTPUT
+ LOG(LINFO, ("Displace (0):", handle->GetOverlayDebugInfo(), "->", parentOverlay->GetOverlayDebugInfo()));
+ #endif
#ifdef COLLECT_DISPLACEMENT_INFO
- m_displacementInfo.emplace_back(DisplacementData(info.m_handle->GetPixelRect(modelView, is3dMode).Center(),
- handle->GetPixelRect(modelView, is3dMode).Center(),
- dp::Color(0, 0, 255, 255)));
+ m_displacementInfo.emplace_back(DisplacementData(handle->GetExtendedPixelRect(modelView).Center(),
+ parentOverlay->GetExtendedPixelRect(modelView).Center(),
+ dp::Color(0, 255, 0, 255)));
#endif
- return;
}
+
+ #ifdef DEBUG_OVERLAYS_OUTPUT
+ LOG(LINFO, ("Displace (1):", rivalHandle->GetOverlayDebugInfo(), "->", handle->GetOverlayDebugInfo()));
+ #endif
+
+ #ifdef COLLECT_DISPLACEMENT_INFO
+ m_displacementInfo.emplace_back(DisplacementData(rivalHandle->GetExtendedPixelRect(modelView).Center(),
+ handle->GetExtendedPixelRect(modelView).Center(),
+ dp::Color(0, 0, 255, 255)));
+ #endif
+ return;
}
}
// Current overlay displaces other overlay, delete them.
- for (auto const & info : elements)
- AddHandleToDelete(info);
+ for (auto const & rivalHandle : rivals)
+ AddHandleToDelete(rivalHandle);
for (auto const & handleToDelete : m_handlesToDelete)
{
Erase(handleToDelete);
-#ifdef COLLECT_DISPLACEMENT_INFO
- m_displacementInfo.emplace_back(DisplacementData(handle->GetPixelRect(modelView, is3dMode).Center(),
- handleToDelete.m_handle->GetPixelRect(modelView, is3dMode).Center(),
- dp::Color(0, 0, 255, 255)));
-#endif
+ #ifdef DEBUG_OVERLAYS_OUTPUT
+ LOG(LINFO, ("Displace (2):", handle->GetOverlayDebugInfo(), "->", handleToDelete->GetOverlayDebugInfo()));
+ #endif
+
+ #ifdef COLLECT_DISPLACEMENT_INFO
+ m_displacementInfo.emplace_back(DisplacementData(handle->GetExtendedPixelRect(modelView).Center(),
+ handleToDelete->GetExtendedPixelRect(modelView).Center(),
+ dp::Color(0, 0, 255, 255)));
+ #endif
}
m_handlesToDelete.clear();
- TBase::Add(detail::OverlayInfo(handle), pixelRect);
+ TBase::Add(handle, pixelRect);
}
void OverlayTree::EndOverlayPlacing()
{
ASSERT(IsNeedUpdate(), ());
- HandleComparator comparator(m_followingMode);
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ LOG(LINFO, ("- BEGIN OVERLAYS PLACING"));
+#endif
+
+ HandleComparator comparator(false /* enableMask */, m_followingMode);
for (int rank = 0; rank < dp::OverlayRanksCount; rank++)
{
sort(m_handles[rank].begin(), m_handles[rank].end(), comparator);
for (auto const & handle : m_handles[rank])
{
- detail::OverlayInfo parentOverlay;
+ ref_ptr<OverlayHandle> parentOverlay;
if (!CheckHandle(handle, rank, parentOverlay))
continue;
@@ -230,56 +266,59 @@ void OverlayTree::EndOverlayPlacing()
m_handles[rank].clear();
}
- ForEach([] (detail::OverlayInfo const & info)
+ ForEach([] (ref_ptr<OverlayHandle> const & h)
{
- info.m_handle->SetIsVisible(true);
+ h->SetIsVisible(true);
});
m_frameCounter = 0;
+
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ LOG(LINFO, ("- END OVERLAYS PLACING"));
+#endif
}
bool OverlayTree::CheckHandle(ref_ptr<OverlayHandle> handle, int currentRank,
- detail::OverlayInfo & parentOverlay) const
+ ref_ptr<OverlayHandle> & parentOverlay) const
{
if (currentRank == dp::OverlayRank0)
return true;
int const seachingRank = currentRank - 1;
- return FindNode([&](detail::OverlayInfo const & info) -> bool
+ return FindNode([&](ref_ptr<OverlayHandle> const & h) -> bool
{
- if (info.m_handle->GetFeatureID() == handle->GetFeatureID() &&
- info.m_handle->GetOverlayRank() == seachingRank)
+ if (h->GetFeatureID() == handle->GetFeatureID() && h->GetOverlayRank() == seachingRank)
{
- parentOverlay = info;
+ parentOverlay = h;
return true;
}
return false;
});
}
-void OverlayTree::AddHandleToDelete(detail::OverlayInfo const & overlay)
+void OverlayTree::AddHandleToDelete(ref_ptr<OverlayHandle> const & handle)
{
- if (overlay.m_handle->IsBound())
+ if (handle->IsBound())
{
- ForEach([&](detail::OverlayInfo const & info)
+ ForEach([&](ref_ptr<OverlayHandle> const & h)
{
- if (info.m_handle->GetFeatureID() == overlay.m_handle->GetFeatureID())
+ if (h->GetFeatureID() == handle->GetFeatureID())
{
if (find(m_handlesToDelete.begin(),
- m_handlesToDelete.end(), info) == m_handlesToDelete.end())
- m_handlesToDelete.push_back(info);
+ m_handlesToDelete.end(), h) == m_handlesToDelete.end())
+ m_handlesToDelete.push_back(h);
}
});
}
else
{
if (find(m_handlesToDelete.begin(),
- m_handlesToDelete.end(), overlay) == m_handlesToDelete.end())
- m_handlesToDelete.push_back(overlay);
+ m_handlesToDelete.end(), handle) == m_handlesToDelete.end())
+ m_handlesToDelete.push_back(handle);
}
}
-void OverlayTree::Select(m2::PointD const & glbPoint, TSelectResult & result) const
+void OverlayTree::Select(m2::PointD const & glbPoint, TOverlayContainer & result) const
{
ScreenBase const & screen = m_traits.m_modelView;
m2::PointD const pxPoint = screen.GtoP(glbPoint);
@@ -288,27 +327,27 @@ void OverlayTree::Select(m2::PointD const & glbPoint, TSelectResult & result) co
m2::RectD rect(pxPoint, pxPoint);
rect.Inflate(kSearchRectHalfSize, kSearchRectHalfSize);
- ForEach([&](detail::OverlayInfo const & info)
+ ForEach([&](ref_ptr<OverlayHandle> const & h)
{
- if (rect.IsPointInside(info.m_handle->GetPivot(screen, false)))
- result.push_back(info.m_handle);
+ if (rect.IsPointInside(h->GetPivot(screen, false)))
+ result.push_back(h);
});
}
-void OverlayTree::Select(m2::RectD const & rect, TSelectResult & result) const
+void OverlayTree::Select(m2::RectD const & rect, TOverlayContainer & result) const
{
ScreenBase screen = m_traits.m_modelView;
- ForEachInRect(rect, [&](detail::OverlayInfo const & info)
+ ForEachInRect(rect, [&](ref_ptr<OverlayHandle> const & h)
{
- if (info.m_handle->IsVisible() && info.m_handle->GetFeatureID().IsValid())
+ if (h->IsVisible() && h->GetFeatureID().IsValid())
{
OverlayHandle::Rects shape;
- info.m_handle->GetPixelShape(screen, shape, screen.isPerspective());
+ h->GetPixelShape(screen, shape, screen.isPerspective());
for (m2::RectF const & rShape : shape)
{
if (rShape.IsIntersect(m2::RectF(rect)))
{
- result.push_back(info.m_handle);
+ result.push_back(h);
break;
}
}
diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp
index c1094b18ad..d56ef3b43f 100644
--- a/drape/overlay_tree.hpp
+++ b/drape/overlay_tree.hpp
@@ -18,36 +18,23 @@ namespace dp
namespace detail
{
-struct OverlayInfo
-{
- ref_ptr<OverlayHandle> m_handle;
-
- OverlayInfo() = default;
- OverlayInfo(ref_ptr<OverlayHandle> handle)
- : m_handle(handle)
- {}
-
- bool operator==(OverlayInfo const & rhs) const
- {
- return m_handle == rhs.m_handle;
- }
-};
-
struct OverlayTraits
{
ScreenBase m_modelView;
- inline m2::RectD const LimitRect(OverlayInfo const & info)
+ inline m2::RectD const LimitRect(ref_ptr<OverlayHandle> const & handle)
{
- return info.m_handle->GetExtendedPixelRect(m_modelView);
+ return handle->GetExtendedPixelRect(m_modelView);
}
};
}
-class OverlayTree : public m4::Tree<detail::OverlayInfo, detail::OverlayTraits>
+using TOverlayContainer = buffer_vector<ref_ptr<OverlayHandle>, 8>;
+
+class OverlayTree : public m4::Tree<ref_ptr<OverlayHandle>, detail::OverlayTraits>
{
- using TBase = m4::Tree<detail::OverlayInfo, detail::OverlayTraits>;
+ using TBase = m4::Tree<ref_ptr<OverlayHandle>, detail::OverlayTraits>;
public:
OverlayTree();
@@ -60,9 +47,8 @@ public:
void Add(ref_ptr<OverlayHandle> handle);
void EndOverlayPlacing();
- using TSelectResult = buffer_vector<ref_ptr<OverlayHandle>, 8>;
- void Select(m2::RectD const & rect, TSelectResult & result) const;
- void Select(m2::PointD const & glbPoint, TSelectResult & result) const;
+ void Select(m2::RectD const & rect, TOverlayContainer & result) const;
+ void Select(m2::PointD const & glbPoint, TOverlayContainer & result) const;
void SetFollowingMode(bool mode);
@@ -83,14 +69,14 @@ public:
private:
ScreenBase const & GetModelView() const { return m_traits.m_modelView; }
void InsertHandle(ref_ptr<OverlayHandle> handle,
- detail::OverlayInfo const & parentOverlay);
+ ref_ptr<OverlayHandle> const & parentOverlay);
bool CheckHandle(ref_ptr<OverlayHandle> handle, int currentRank,
- detail::OverlayInfo & parentOverlay) const;
- void AddHandleToDelete(detail::OverlayInfo const & overlay);
+ ref_ptr<OverlayHandle> & parentOverlay) const;
+ void AddHandleToDelete(ref_ptr<OverlayHandle> const & handle);
int m_frameCounter;
array<vector<ref_ptr<OverlayHandle>>, dp::OverlayRanksCount> m_handles;
- vector<detail::OverlayInfo> m_handlesToDelete;
+ vector<ref_ptr<OverlayHandle>> m_handlesToDelete;
bool m_followingMode;
#ifdef COLLECT_DISPLACEMENT_INFO
diff --git a/drape/render_bucket.cpp b/drape/render_bucket.cpp
index ce031e9f54..4c8a96af45 100644
--- a/drape/render_bucket.cpp
+++ b/drape/render_bucket.cpp
@@ -119,7 +119,8 @@ void RenderBucket::RenderDebug(ScreenBase const & screen) const
if (screen.isPerspective() && !screen.PixelRectIn3d().IsIntersect(m2::RectD(rect)))
continue;
- DebugRectRenderer::Instance().DrawRect(screen, rect);
+ DebugRectRenderer::Instance().DrawRect(screen, rect, handle->IsVisible() ?
+ dp::Color::Green() : dp::Color::Red());
}
}
}
diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp
index 4a6c264ed8..21d8c14709 100644
--- a/drape_frontend/apply_feature_functors.cpp
+++ b/drape_frontend/apply_feature_functors.cpp
@@ -222,6 +222,7 @@ void BaseApplyFeature::ExtractCaptionParams(CaptionDefProto const * primaryProto
params.m_primaryOffset = GetOffset(primaryProto);
params.m_primaryOptional = primaryProto->has_is_optional() ? primaryProto->is_optional() : true;
params.m_secondaryOptional = true;
+ params.m_hasMark = m_captions.HasMark();
if (secondaryProto)
{
@@ -286,7 +287,10 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule)
params.m_rank = m_rank;
params.m_posZ = m_posZ;
if(!params.m_primaryText.empty() || !params.m_secondaryText.empty())
- m_insertShape(make_unique_dp<TextShape>(m_centerPoint, params, hasPOI));
+ {
+ m_insertShape(make_unique_dp<TextShape>(m_centerPoint, params, hasPOI, 0 /* textIndex */,
+ true /* affectedByZoomPriority */));
+ }
}
}
@@ -558,6 +562,7 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule)
CaptionDefProtoToFontDecl(pCaptionRule, fontDecl);
PathTextViewParams params;
+ params.m_featureID = m_id;
params.m_depth = depth;
params.m_minVisibleScale = m_minVisibleScale;
params.m_rank = m_rank;
@@ -639,7 +644,7 @@ void ApplyLineFeature::Finish()
viewParams.m_minVisibleScale = m_minVisibleScale;
viewParams.m_rank = m_rank;
viewParams.m_anchor = dp::Center;
- viewParams.m_featureID = FeatureID();
+ viewParams.m_featureID = m_id;
viewParams.m_primaryText = roadNumber;
viewParams.m_primaryTextFont = font;
viewParams.m_primaryOffset = m2::PointF(0, 0);
@@ -648,11 +653,13 @@ void ApplyLineFeature::Finish()
viewParams.m_extendingSize = m_shieldRule->has_min_distance() ? mainScale * m_shieldRule->min_distance() : 0;
m2::Spline::iterator it = m_spline.CreateIterator();
+ size_t textIndex = 0;
while (!it.BeginAgain())
{
m_insertShape(make_unique_dp<TextShape>(it.m_pos, viewParams, false /* hasPOI */,
- false /* affectedByZoomPriority */));
+ textIndex, false /* affectedByZoomPriority */));
it.Advance(splineStep);
+ textIndex++;
}
}
}
diff --git a/drape_frontend/area_shape.hpp b/drape_frontend/area_shape.hpp
index 5c3d30bfba..7dc2844082 100644
--- a/drape_frontend/area_shape.hpp
+++ b/drape_frontend/area_shape.hpp
@@ -26,8 +26,6 @@ public:
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::AreaPriority; }
-
private:
vector<m2::PointF> m_vertexes;
vector<BuildingEdge> m_buildingEdges;
diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp
index 2e8d51b273..ea71a11cba 100644
--- a/drape_frontend/backend_renderer.cpp
+++ b/drape_frontend/backend_renderer.cpp
@@ -152,6 +152,16 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
case Message::FinishReading:
{
ref_ptr<FinishReadingMessage> msg = message;
+
+ TOverlaysRenderData overlays;
+ overlays.swap(m_overlays);
+ if (!overlays.empty())
+ {
+ m_commutator->PostMessage(ThreadsCommutator::RenderThread,
+ make_unique_dp<FlushOverlaysMessage>(move(overlays)),
+ MessagePriority::Normal);
+ }
+
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<FinishReadingMessage>(move(msg->MoveTiles())),
MessagePriority::Normal);
@@ -169,6 +179,26 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
}
break;
}
+ case Message::OverlayMapShapeReaded:
+ {
+ ref_ptr<OverlayMapShapeReadedMessage> msg = message;
+ auto const & tileKey = msg->GetKey();
+ if (m_requestedTiles->CheckTileKey(tileKey) && m_readManager->CheckTileKey(tileKey))
+ {
+ OverlayBatcher batcher(tileKey);
+ for (drape_ptr<MapShape> const & shape : msg->GetShapes())
+ batcher.Batch(shape, m_texMng);
+
+ TOverlaysRenderData renderData;
+ batcher.Finish(renderData);
+ if (!renderData.empty())
+ {
+ m_overlays.reserve(m_overlays.size() + renderData.size());
+ move(renderData.begin(), renderData.end(), back_inserter(m_overlays));
+ }
+ }
+ break;
+ }
case Message::UpdateUserMarkLayer:
{
ref_ptr<UpdateUserMarkLayerMessage> msg = message;
diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp
index 6f18e246f5..9d31892fdf 100644
--- a/drape_frontend/backend_renderer.hpp
+++ b/drape_frontend/backend_renderer.hpp
@@ -4,6 +4,7 @@
#include "drape_frontend/base_renderer.hpp"
#include "drape_frontend/map_data_provider.hpp"
+#include "drape_frontend/overlay_batcher.hpp"
#include "drape_frontend/requested_tiles.hpp"
#include "drape_frontend/viewport.hpp"
@@ -64,7 +65,6 @@ private:
public:
Routine(BackendRenderer & renderer);
- // threads::IRoutine overrides:
void Do() override;
private:
@@ -84,6 +84,8 @@ private:
ref_ptr<RequestedTiles> m_requestedTiles;
+ TOverlaysRenderData m_overlays;
+
#ifdef DEBUG
bool m_isTeardowned;
#endif
diff --git a/drape_frontend/circle_shape.cpp b/drape_frontend/circle_shape.cpp
index 60878e4054..6964533303 100644
--- a/drape_frontend/circle_shape.cpp
+++ b/drape_frontend/circle_shape.cpp
@@ -55,7 +55,7 @@ void CircleShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager>
drape_ptr<dp::OverlayHandle> overlay = make_unique_dp<dp::SquareHandle>(m_params.m_id,
dp::Center, m_pt,
m2::PointD(handleSize, handleSize),
- GetOverlayPriority());
+ GetOverlayPriority(), "");
dp::AttributeProvider provider(1, TriangleCount + 2);
provider.InitStream(0, gpu::SolidTexturingVertex::GetBindingInfo(), make_ref(vertexes.data()));
diff --git a/drape_frontend/circle_shape.hpp b/drape_frontend/circle_shape.hpp
index e7f9d84f48..93091aae4e 100644
--- a/drape_frontend/circle_shape.hpp
+++ b/drape_frontend/circle_shape.hpp
@@ -12,6 +12,7 @@ public:
CircleShape(m2::PointF const & mercatorPt, CircleViewParams const & params);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
+ MapShapeType GetType() const override { return MapShapeType::OverlayType; }
private:
uint64_t GetOverlayPriority() const;
diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro
index 0561c426d7..50403c91cd 100755
--- a/drape_frontend/drape_frontend.pro
+++ b/drape_frontend/drape_frontend.pro
@@ -54,6 +54,7 @@ SOURCES += \
my_position.cpp \
my_position_controller.cpp \
navigator.cpp \
+ overlay_batcher.cpp \
path_symbol_shape.cpp \
path_text_shape.cpp \
poi_symbol_shape.cpp \
@@ -146,6 +147,7 @@ HEADERS += \
my_position.hpp \
my_position_controller.hpp \
navigator.hpp \
+ overlay_batcher.hpp \
path_symbol_shape.hpp \
path_text_shape.hpp \
poi_symbol_shape.hpp \
diff --git a/drape_frontend/engine_context.cpp b/drape_frontend/engine_context.cpp
index 7cefcd6959..b3554fff29 100644
--- a/drape_frontend/engine_context.cpp
+++ b/drape_frontend/engine_context.cpp
@@ -3,6 +3,8 @@
#include "drape_frontend/message_subclasses.hpp"
#include "drape/texture_manager.hpp"
+#include "std/algorithm.hpp"
+
namespace df
{
@@ -12,6 +14,8 @@ EngineContext::EngineContext(TileKey tileKey, ref_ptr<ThreadsCommutator> commuta
, m_commutator(commutator)
, m_texMng(texMng)
{
+ int const kAverageShapesCount = 300;
+ m_overlayShapes.reserve(kAverageShapesCount);
}
ref_ptr<dp::TextureManager> EngineContext::GetTextureManager() const
@@ -29,8 +33,21 @@ void EngineContext::Flush(TMapShapes && shapes)
PostMessage(make_unique_dp<MapShapeReadedMessage>(m_tileKey, move(shapes)));
}
+void EngineContext::FlushOverlays(TMapShapes && shapes)
+{
+ m_overlayShapes.reserve(m_overlayShapes.size() + shapes.size());
+ move(shapes.begin(), shapes.end(), back_inserter(m_overlayShapes));
+}
+
void EngineContext::EndReadTile()
{
+ if (!m_overlayShapes.empty())
+ {
+ TMapShapes overlayShapes;
+ overlayShapes.swap(m_overlayShapes);
+ PostMessage(make_unique_dp<OverlayMapShapeReadedMessage>(m_tileKey, move(overlayShapes)));
+ }
+
PostMessage(make_unique_dp<TileReadEndMessage>(m_tileKey));
}
diff --git a/drape_frontend/engine_context.hpp b/drape_frontend/engine_context.hpp
index e9330f1892..ac29bc9fd6 100644
--- a/drape_frontend/engine_context.hpp
+++ b/drape_frontend/engine_context.hpp
@@ -28,6 +28,7 @@ public:
void BeginReadTile();
void Flush(TMapShapes && shapes);
+ void FlushOverlays(TMapShapes && shapes);
void EndReadTile();
private:
@@ -36,6 +37,7 @@ private:
TileKey m_tileKey;
ref_ptr<ThreadsCommutator> m_commutator;
ref_ptr<dp::TextureManager> m_texMng;
+ TMapShapes m_overlayShapes;
};
} // namespace df
diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp
index e6c51bc50a..cd2e72111e 100755
--- a/drape_frontend/frontend_renderer.cpp
+++ b/drape_frontend/frontend_renderer.cpp
@@ -249,14 +249,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
dp::GLState const & state = msg->GetState();
TileKey const & key = msg->GetKey();
drape_ptr<dp::RenderBucket> bucket = msg->AcceptBuffer();
- ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
- ref_ptr<dp::GpuProgram> program3d = m_gpuProgramManager->GetProgram(state.GetProgram3dIndex());
- bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
- if (isPerspective)
- program3d->Bind();
- else
- program->Bind();
- bucket->GetBuffer()->Build(isPerspective ? program3d : program);
+ PrepareBucket(state, bucket);
if (!IsUserMarkLayer(key))
{
if (CheckTileGenerations(key))
@@ -264,12 +257,33 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
}
else
{
+ ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
+ ref_ptr<dp::GpuProgram> program3d = m_gpuProgramManager->GetProgram(state.GetProgram3dIndex());
+
m_userMarkRenderGroups.emplace_back(make_unique_dp<UserMarkRenderGroup>(state, key, move(bucket)));
m_userMarkRenderGroups.back()->SetRenderParams(program, program3d, make_ref(&m_generalUniforms));
}
break;
}
+ case Message::FlushOverlays:
+ {
+ ref_ptr<FlushOverlaysMessage> msg = message;
+ int const zoom = GetCurrentZoomLevelForData();
+ TOverlaysRenderData renderData = msg->AcceptRenderData();
+ for (auto & overlayRenderData : renderData)
+ {
+ ASSERT(!IsUserMarkLayer(overlayRenderData.m_tileKey), ());
+ if (CheckTileGenerations(overlayRenderData.m_tileKey))
+ {
+ PrepareBucket(overlayRenderData.m_state, overlayRenderData.m_bucket);
+ m_tileTree->ProcessTile(overlayRenderData.m_tileKey, zoom,
+ overlayRenderData.m_state, move(overlayRenderData.m_bucket));
+ }
+ }
+ break;
+ }
+
case Message::FinishReading:
{
ref_ptr<FinishReadingMessage> msg = message;
@@ -415,7 +429,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
double offsetZ = 0.0;
if (m_userEventStream.GetCurrentScreen().isPerspective())
{
- dp::OverlayTree::TSelectResult selectResult;
+ dp::TOverlayContainer selectResult;
m_overlayTree->Select(msg->GetPosition(), selectResult);
for (ref_ptr<dp::OverlayHandle> handle : selectResult)
offsetZ = max(offsetZ, handle->GetPivotZ());
@@ -844,7 +858,7 @@ FeatureID FrontendRenderer::GetVisiblePOI(m2::PointD const & pixelPoint) const
FeatureID FrontendRenderer::GetVisiblePOI(m2::RectD const & pixelRect) const
{
m2::PointD pt = pixelRect.Center();
- dp::OverlayTree::TSelectResult selectResult;
+ dp::TOverlayContainer selectResult;
m_overlayTree->Select(pixelRect, selectResult);
double dist = numeric_limits<double>::max();
@@ -1034,6 +1048,18 @@ void FrontendRenderer::RenderOverlayLayer(ScreenBase const & modelView)
RenderSingleGroup(modelView, make_ref(group));
}
+void FrontendRenderer::PrepareBucket(dp::GLState const & state, drape_ptr<dp::RenderBucket> & bucket)
+{
+ ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
+ ref_ptr<dp::GpuProgram> program3d = m_gpuProgramManager->GetProgram(state.GetProgram3dIndex());
+ bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
+ if (isPerspective)
+ program3d->Bind();
+ else
+ program->Bind();
+ bucket->GetBuffer()->Build(isPerspective ? program3d : program);
+}
+
void FrontendRenderer::MergeBuckets()
{
if (BatchMergeHelper::IsMergeSupported() == false)
@@ -1423,7 +1449,7 @@ void FrontendRenderer::Routine::Do()
if (activityTimer.ElapsedSeconds() > kMaxInactiveSeconds)
{
// Process a message or wait for a message.
- m_renderer.ProcessSingleMessage();
+ m_renderer.ProcessSingleMessage(false);
activityTimer.Reset();
}
else
diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp
index b4053cffcf..7f9b728a82 100755
--- a/drape_frontend/frontend_renderer.hpp
+++ b/drape_frontend/frontend_renderer.hpp
@@ -141,6 +141,7 @@ protected:
private:
void OnResize(ScreenBase const & screen);
void RenderScene(ScreenBase const & modelView);
+ void PrepareBucket(dp::GLState const & state, drape_ptr<dp::RenderBucket> & bucket);
void MergeBuckets();
void RenderSingleGroup(ScreenBase const & modelView, ref_ptr<BaseRenderGroup> group);
void RefreshProjection(ScreenBase const & screen);
diff --git a/drape_frontend/line_shape.hpp b/drape_frontend/line_shape.hpp
index 0c4dca2a32..b1f583e645 100644
--- a/drape_frontend/line_shape.hpp
+++ b/drape_frontend/line_shape.hpp
@@ -40,7 +40,6 @@ public:
void Prepare(ref_ptr<dp::TextureManager> textures) const override;
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::LinePriority; }
private:
template <typename TBuilder>
diff --git a/drape_frontend/map_shape.hpp b/drape_frontend/map_shape.hpp
index 813f3ad8b0..8253a4b4b7 100644
--- a/drape_frontend/map_shape.hpp
+++ b/drape_frontend/map_shape.hpp
@@ -14,14 +14,12 @@ namespace dp
namespace df
{
-// Priority of shapes' processing (descending order).
-enum MapShapePriority
+enum MapShapeType
{
- AreaPriority = 0,
- TextAndPoiPriority,
- LinePriority,
+ GeometryType = 0,
+ OverlayType,
- PrioritiesCount
+ MapShapeTypeCount
};
class MapShape
@@ -30,27 +28,60 @@ public:
virtual ~MapShape(){}
virtual void Prepare(ref_ptr<dp::TextureManager> textures) const {}
virtual void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const = 0;
- virtual MapShapePriority GetPriority() const { return MapShapePriority::AreaPriority; }
+ virtual MapShapeType GetType() const { return MapShapeType::GeometryType; }
};
using TMapShapes = vector<drape_ptr<MapShape>>;
-class MapShapeReadedMessage : public Message
+class MapShapeMessage : public Message
{
public:
- MapShapeReadedMessage(TileKey const & key, TMapShapes && shapes)
- : m_key(key), m_shapes(move(shapes))
+ MapShapeMessage(TileKey const & key)
+ : m_tileKey(key)
{}
- Type GetType() const override { return Message::MapShapeReaded; }
+ TileKey const & GetKey() const { return m_tileKey; }
+
+private:
+ TileKey m_tileKey;
+};
+
+class TileReadStartMessage : public MapShapeMessage
+{
+public:
+ TileReadStartMessage(TileKey const & key) : MapShapeMessage(key) {}
+ Type GetType() const override { return Message::TileReadStarted; }
+};
+
+class TileReadEndMessage : public MapShapeMessage
+{
+public:
+ TileReadEndMessage(TileKey const & key) : MapShapeMessage(key) {}
+ Type GetType() const override { return Message::TileReadEnded; }
+};
- TileKey const & GetKey() const { return m_key; }
+class MapShapeReadedMessage : public MapShapeMessage
+{
+public:
+ MapShapeReadedMessage(TileKey const & key, TMapShapes && shapes)
+ : MapShapeMessage(key), m_shapes(move(shapes))
+ {}
+ Type GetType() const override { return Message::MapShapeReaded; }
TMapShapes const & GetShapes() { return m_shapes; }
private:
- TileKey m_key;
TMapShapes m_shapes;
};
+class OverlayMapShapeReadedMessage : public MapShapeReadedMessage
+{
+public:
+ OverlayMapShapeReadedMessage(TileKey const & key, TMapShapes && shapes)
+ : MapShapeReadedMessage(key, move(shapes))
+ {}
+
+ Type GetType() const override { return Message::OverlayMapShapeReaded; }
+};
+
} // namespace df
diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp
index 621b9ca1f6..7f67ff4a4d 100644
--- a/drape_frontend/message.hpp
+++ b/drape_frontend/message.hpp
@@ -13,7 +13,9 @@ public:
TileReadEnded,
FinishReading,
FlushTile,
+ FlushOverlays,
MapShapeReaded,
+ OverlayMapShapeReaded,
UpdateReadManager,
InvalidateRect,
InvalidateReadManagerRect,
diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp
index e80cc970a4..0d457c3375 100644
--- a/drape_frontend/message_subclasses.hpp
+++ b/drape_frontend/message_subclasses.hpp
@@ -7,13 +7,14 @@
#include "drape_frontend/color_constants.hpp"
#include "drape_frontend/gps_track_point.hpp"
#include "drape_frontend/gps_track_shape.hpp"
-#include "drape_frontend/route_builder.hpp"
+#include "drape_frontend/message.hpp"
#include "drape_frontend/my_position.hpp"
+#include "drape_frontend/overlay_batcher.hpp"
+#include "drape_frontend/route_builder.hpp"
#include "drape_frontend/selection_shape.hpp"
-#include "drape_frontend/message.hpp"
-#include "drape_frontend/viewport.hpp"
#include "drape_frontend/tile_utils.hpp"
#include "drape_frontend/user_marks_provider.hpp"
+#include "drape_frontend/viewport.hpp"
#include "geometry/polyline2d.hpp"
#include "geometry/rect2d.hpp"
@@ -87,24 +88,6 @@ private:
TileKey m_tileKey;
};
-class TileReadStartMessage : public BaseTileMessage
-{
-public:
- TileReadStartMessage(TileKey const & key)
- : BaseTileMessage(key) {}
-
- Type GetType() const override { return Message::TileReadStarted; }
-};
-
-class TileReadEndMessage : public BaseTileMessage
-{
-public:
- TileReadEndMessage(TileKey const & key)
- : BaseTileMessage(key) {}
-
- Type GetType() const override { return Message::TileReadEnded; }
-};
-
class FinishReadingMessage : public Message
{
public:
@@ -140,6 +123,18 @@ private:
drape_ptr<dp::RenderBucket> m_buffer;
};
+class FlushOverlaysMessage : public Message
+{
+public:
+ FlushOverlaysMessage(TOverlaysRenderData && data) : m_data(move(data)) {}
+
+ Type GetType() const override { return Message::FlushOverlays; }
+ TOverlaysRenderData && AcceptRenderData() { return move(m_data); }
+
+private:
+ TOverlaysRenderData m_data;
+};
+
class InvalidateRectMessage : public Message
{
public:
diff --git a/drape_frontend/overlay_batcher.cpp b/drape_frontend/overlay_batcher.cpp
new file mode 100644
index 0000000000..c03cc06652
--- /dev/null
+++ b/drape_frontend/overlay_batcher.cpp
@@ -0,0 +1,43 @@
+#include "drape_frontend/overlay_batcher.hpp"
+
+#include "drape_frontend/map_shape.hpp"
+
+#include "drape/batcher.hpp"
+#include "drape/render_bucket.hpp"
+#include "drape/texture_manager.hpp"
+
+namespace df
+{
+
+uint32_t const kOverlayIndexBufferSize = 30000;
+uint32_t const kOverlayVertexBufferSize = 20000;
+
+OverlayBatcher::OverlayBatcher(TileKey const & key)
+ : m_batcher(kOverlayIndexBufferSize, kOverlayVertexBufferSize)
+{
+ int const kAverageRenderDataCount = 5;
+ m_data.reserve(kAverageRenderDataCount);
+
+ m_batcher.StartSession([this, key](dp::GLState const & state, drape_ptr<dp::RenderBucket> && bucket)
+ {
+ FlushGeometry(key, state, move(bucket));
+ });
+}
+
+void OverlayBatcher::Batch(drape_ptr<MapShape> const & shape, ref_ptr<dp::TextureManager> texMng)
+{
+ shape->Draw(make_ref(&m_batcher), texMng);
+}
+
+void OverlayBatcher::Finish(TOverlaysRenderData & data)
+{
+ m_batcher.EndSession();
+ data.swap(m_data);
+}
+
+void OverlayBatcher::FlushGeometry(TileKey const & key, dp::GLState const & state, drape_ptr<dp::RenderBucket> && bucket)
+{
+ m_data.emplace_back(key, state, move(bucket));
+}
+
+} // namespace df
diff --git a/drape_frontend/overlay_batcher.hpp b/drape_frontend/overlay_batcher.hpp
new file mode 100644
index 0000000000..d1b5c9e549
--- /dev/null
+++ b/drape_frontend/overlay_batcher.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "drape/batcher.hpp"
+#include "drape/glstate.hpp"
+#include "drape/pointers.hpp"
+
+#include "drape_frontend/tile_key.hpp"
+
+#include "std/vector.hpp"
+
+namespace dp
+{
+class TextureManager;
+class RenderBucket;
+} // namespace dp
+
+namespace df
+{
+
+class MapShape;
+
+struct OverlayRenderData
+{
+ TileKey m_tileKey;
+ dp::GLState m_state;
+ drape_ptr<dp::RenderBucket> m_bucket;
+
+ OverlayRenderData(TileKey const & key, dp::GLState const & state, drape_ptr<dp::RenderBucket> && bucket)
+ : m_tileKey(key), m_state(state), m_bucket(move(bucket))
+ {}
+};
+
+using TOverlaysRenderData = vector<OverlayRenderData>;
+
+class OverlayBatcher
+{
+public:
+ OverlayBatcher(TileKey const & key);
+ void Batch(drape_ptr<MapShape> const & shape, ref_ptr<dp::TextureManager> texMng);
+ void Finish(TOverlaysRenderData & data);
+
+private:
+ void FlushGeometry(TileKey const & key, dp::GLState const & state, drape_ptr<dp::RenderBucket> && bucket);
+
+ dp::Batcher m_batcher;
+ TOverlaysRenderData m_data;
+};
+
+} // namespace df
diff --git a/drape_frontend/path_symbol_shape.hpp b/drape_frontend/path_symbol_shape.hpp
index 2366de3544..d02c36c0d6 100644
--- a/drape_frontend/path_symbol_shape.hpp
+++ b/drape_frontend/path_symbol_shape.hpp
@@ -13,7 +13,6 @@ class PathSymbolShape : public MapShape
public:
PathSymbolShape(m2::SharedSpline const & spline, PathSymbolViewParams const & params);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::LinePriority; }
private:
PathSymbolViewParams m_params;
diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp
index f8ac3ce198..0a23de4e52 100644
--- a/drape_frontend/path_text_shape.cpp
+++ b/drape_frontend/path_text_shape.cpp
@@ -29,14 +29,14 @@ namespace
class PathTextHandle : public df::TextHandle
{
public:
- PathTextHandle(m2::SharedSpline const & spl,
+ PathTextHandle(FeatureID const & id, m2::SharedSpline const & spl,
df::SharedTextLayout const & layout,
float mercatorOffset, float depth,
uint32_t textIndex, uint64_t priority,
uint64_t priorityFollowingMode,
ref_ptr<dp::TextureManager> textureManager,
bool isBillboard)
- : TextHandle(FeatureID(), layout->GetText(), dp::Center, priority, textureManager, isBillboard)
+ : TextHandle(id, layout->GetText(), dp::Center, priority, textureManager, isBillboard)
, m_spline(spl)
, m_layout(layout)
, m_textIndex(textIndex)
@@ -62,15 +62,18 @@ public:
if (screen.isPerspective())
{
+ // In perspective mode we draw the first label only.
+ if (m_textIndex != 0)
+ return false;
+
float pixelOffset = 0.0f;
- uint32_t startIndex = 0;
bool foundOffset = false;
for (auto pos : globalPoints)
{
pos = screen.GtoP(pos);
if (!screen.PixelRect().IsPointInside(pos))
{
- if ((foundOffset = CalculateOffsets(pixelSpline, startIndex, pixelOffset)))
+ if ((foundOffset = CalculatePerspectiveOffsets(pixelSpline, pixelOffset)))
break;
pixelSpline = m2::Spline(m_spline->GetSize());
@@ -79,7 +82,8 @@ public:
pixelSpline.AddPoint(screen.PtoP3d(pos));
}
- if (!foundOffset && !CalculateOffsets(pixelSpline, startIndex, pixelOffset))
+ // We aren't able to place the only label anywhere.
+ if (!foundOffset && !CalculatePerspectiveOffsets(pixelSpline, pixelOffset))
return false;
centerPointIter.Attach(pixelSpline);
@@ -147,11 +151,13 @@ public:
r.Offset(pxPivotPerspective);
}
else
+ {
r = m2::RectF(GetPerspectiveRect(m2::RectD(r), screen));
+ }
}
- m2::RectD const screenRect = perspective ? screen.PixelRectIn3d() : screen.PixelRect();
- if (screenRect.IsIntersect(m2::RectD(r)))
+ bool const needAddRect = perspective ? !screen.IsReverseProjection3d(r.Center()) : true;
+ if (needAddRect)
rects.emplace_back(move(r));
}
}
@@ -181,23 +187,17 @@ public:
}
private:
- bool CalculateOffsets(const m2::Spline & pixelSpline, uint32_t & startIndex, float & pixelOffset) const
+ bool CalculatePerspectiveOffsets(const m2::Spline & pixelSpline, float & pixelOffset) const
{
if (pixelSpline.GetSize() < 2)
return false;
- vector<float> offsets;
- df::PathTextLayout::CalculatePositions(offsets, pixelSpline.GetLength(), 1.0,
- m_layout->GetPixelLength());
-
- if (startIndex + offsets.size() <= m_textIndex)
- {
- startIndex += offsets.size();
+ float offset = 0.0f;
+ if (!df::PathTextLayout::CalculatePerspectivePosition(pixelSpline.GetLength(),
+ m_layout->GetPixelLength(), offset))
return false;
- }
- ASSERT_LESS_OR_EQUAL(startIndex, m_textIndex, ());
- pixelOffset = offsets[m_textIndex - startIndex];
+ pixelOffset = offset;
return true;
}
@@ -222,17 +222,18 @@ PathTextShape::PathTextShape(m2::SharedSpline const & spline,
, m_params(params)
{}
-uint64_t PathTextShape::GetOverlayPriority(bool followingMode) const
+uint64_t PathTextShape::GetOverlayPriority(size_t textIndex, bool followingMode) const
{
- // Overlay priority for path text shapes considers length of the text.
- // Greater test length has more priority, because smaller texts have more chances to be shown along the road.
- // [6 bytes - standard overlay priority][1 byte - reserved][1 byte - length].
- static uint64_t constexpr kMask = ~static_cast<uint64_t>(0xFF);
+ // Overlay priority for path text shapes considers length of the text and index of text.
+ // Greater text length has more priority, because smaller texts have more chances to be shown along the road.
+ // [6 bytes - standard overlay priority][1 byte - length][1 byte - path text index].
+ static uint64_t constexpr kMask = ~static_cast<uint64_t>(0xFFFF);
uint64_t priority = dp::kPriorityMaskAll;
if (!followingMode)
priority = dp::CalculateOverlayPriority(m_params.m_minVisibleScale, m_params.m_rank, m_params.m_depth);
priority &= kMask;
- priority |= (static_cast<uint8_t>(m_params.m_text.size()));
+ priority |= (static_cast<uint8_t>(m_params.m_text.size()) << 8);
+ priority |= static_cast<uint8_t>(textIndex);
return priority;
}
@@ -267,10 +268,10 @@ void PathTextShape::DrawPathTextPlain(ref_ptr<dp::TextureManager> textures,
provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data()));
provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data()));
- drape_ptr<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_spline, layoutPtr, offset,
+ drape_ptr<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_params.m_featureID, m_spline, layoutPtr, offset,
m_params.m_depth, textIndex,
- GetOverlayPriority(false /* followingMode */),
- GetOverlayPriority(true /* followingMode */),
+ GetOverlayPriority(textIndex, false /* followingMode */),
+ GetOverlayPriority(textIndex, true /* followingMode */),
textures, true);
batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4);
}
@@ -308,10 +309,10 @@ void PathTextShape::DrawPathTextOutlined(ref_ptr<dp::TextureManager> textures,
provider.InitStream(0, gpu::TextOutlinedStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data()));
provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data()));
- drape_ptr<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_spline, layoutPtr, offset,
+ drape_ptr<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_params.m_featureID, m_spline, layoutPtr, offset,
m_params.m_depth, textIndex,
- GetOverlayPriority(false /* followingMode */),
- GetOverlayPriority(true /* followingMode */),
+ GetOverlayPriority(textIndex, false /* followingMode */),
+ GetOverlayPriority(textIndex, true /* followingMode */),
textures, true);
batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4);
}
diff --git a/drape_frontend/path_text_shape.hpp b/drape_frontend/path_text_shape.hpp
index b9dde17f22..d229f52858 100644
--- a/drape_frontend/path_text_shape.hpp
+++ b/drape_frontend/path_text_shape.hpp
@@ -9,15 +9,16 @@ namespace df
{
class PathTextLayout;
+
class PathTextShape : public MapShape
{
public:
PathTextShape(m2::SharedSpline const & spline, PathTextViewParams const & params);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::LinePriority; }
+ MapShapeType GetType() const override { return MapShapeType::OverlayType; }
private:
- uint64_t GetOverlayPriority(bool followingMode) const;
+ uint64_t GetOverlayPriority(size_t textIndex, bool followingMode) const;
void DrawPathTextPlain(ref_ptr<dp::TextureManager> textures,
ref_ptr<dp::Batcher> batcher,
diff --git a/drape_frontend/poi_symbol_shape.cpp b/drape_frontend/poi_symbol_shape.cpp
index 6889e81241..3053deeba2 100644
--- a/drape_frontend/poi_symbol_shape.cpp
+++ b/drape_frontend/poi_symbol_shape.cpp
@@ -55,6 +55,7 @@ void PoiSymbolShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManag
dp::Center,
m_pt, pixelSize,
GetOverlayPriority(),
+ m_params.m_symbolName,
true);
handle->SetPivotZ(m_params.m_posZ);
handle->SetExtendingSize(m_params.m_extendingSize);
diff --git a/drape_frontend/poi_symbol_shape.hpp b/drape_frontend/poi_symbol_shape.hpp
index a198d22452..57230ca8e6 100644
--- a/drape_frontend/poi_symbol_shape.hpp
+++ b/drape_frontend/poi_symbol_shape.hpp
@@ -12,7 +12,7 @@ public:
PoiSymbolShape(m2::PointF const & mercatorPt, PoiSymbolViewParams const & params);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::TextAndPoiPriority; }
+ MapShapeType GetType() const override { return MapShapeType::OverlayType; }
private:
uint64_t GetOverlayPriority() const;
diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp
index e1bbd058d6..dbff396ed1 100644
--- a/drape_frontend/rule_drawer.cpp
+++ b/drape_frontend/rule_drawer.cpp
@@ -11,6 +11,8 @@
#include "indexer/ftypes_matcher.hpp"
#include "base/assert.hpp"
+#include "base/logging.hpp"
+
#include "std/bind.hpp"
//#define DRAW_TILE_NET
@@ -28,13 +30,6 @@ namespace df
int const kLineSimplifyLevelStart = 10;
int const kLineSimplifyLevelEnd = 12;
-size_t kMinFlushSizes[df::PrioritiesCount] =
-{
- 1, // AreaPriority
- 5, // TextAndPoiPriority
- 10, // LinePriority
-};
-
RuleDrawer::RuleDrawer(TDrawerCallback const & fn,
TCheckCancelledCallback const & checkCancelled,
TIsCountryLoadedByNameFn const & isLoadedFn,
@@ -58,8 +53,8 @@ RuleDrawer::RuleDrawer(TDrawerCallback const & fn,
geometryConvertor.SetFromRect(m2::AnyRectD(r));
m_currentScaleGtoP = 1.0f / geometryConvertor.GetScale();
- for (size_t i = 0; i < m_mapShapes.size(); i++)
- m_mapShapes[i].reserve(kMinFlushSizes[i] + 1);
+ int const kAverageOverlaysCount = 200;
+ m_mapShapes[df::OverlayType].reserve(kAverageOverlaysCount);
}
RuleDrawer::~RuleDrawer()
@@ -67,15 +62,14 @@ RuleDrawer::~RuleDrawer()
if (m_wasCancelled)
return;
- for (auto & shapes : m_mapShapes)
- {
- if (shapes.empty())
- continue;
-
- for (auto const & shape : shapes)
- shape->Prepare(m_context->GetTextureManager());
+ for (auto const & shape : m_mapShapes[df::OverlayType])
+ shape->Prepare(m_context->GetTextureManager());
- m_context->Flush(move(shapes));
+ if (!m_mapShapes[df::OverlayType].empty())
+ {
+ TMapShapes overlayShapes;
+ overlayShapes.swap(m_mapShapes[df::OverlayType]);
+ m_context->FlushOverlays(move(overlayShapes));
}
}
@@ -127,7 +121,7 @@ void RuleDrawer::operator()(FeatureType const & f)
auto insertShape = [this](drape_ptr<MapShape> && shape)
{
- int const index = static_cast<int>(shape->GetPriority());
+ int const index = static_cast<int>(shape->GetType());
ASSERT_LESS(index, m_mapShapes.size(), ());
m_mapShapes[index].push_back(move(shape));
};
@@ -257,23 +251,20 @@ void RuleDrawer::operator()(FeatureType const & f)
tp.m_primaryTextFont = dp::FontDecl(dp::Color::Red(), 30);
- insertShape(make_unique_dp<TextShape>(r.Center(), tp, false));
+ insertShape(make_unique_dp<TextShape>(r.Center(), tp, false, 0, true));
#endif
if (CheckCancelled())
return;
- for (size_t i = 0; i < m_mapShapes.size(); i++)
- {
- if (m_mapShapes[i].size() < kMinFlushSizes[i])
- continue;
-
- for (auto const & shape : m_mapShapes[i])
- shape->Prepare(m_context->GetTextureManager());
+ for (auto const & shape : m_mapShapes[df::GeometryType])
+ shape->Prepare(m_context->GetTextureManager());
- TMapShapes mapShapes;
- mapShapes.swap(m_mapShapes[i]);
- m_context->Flush(move(mapShapes));
+ if (!m_mapShapes[df::GeometryType].empty())
+ {
+ TMapShapes geomShapes;
+ geomShapes.swap(m_mapShapes[df::GeometryType]);
+ m_context->Flush(move(geomShapes));
}
}
diff --git a/drape_frontend/rule_drawer.hpp b/drape_frontend/rule_drawer.hpp
index 41e35dd0c0..4af2842783 100644
--- a/drape_frontend/rule_drawer.hpp
+++ b/drape_frontend/rule_drawer.hpp
@@ -47,7 +47,7 @@ private:
bool const m_is3dBuidings;
- array<TMapShapes, df::PrioritiesCount> m_mapShapes;
+ array<TMapShapes, df::MapShapeTypeCount> m_mapShapes;
bool m_wasCancelled;
};
diff --git a/drape_frontend/shape_view_params.hpp b/drape_frontend/shape_view_params.hpp
index 6a7e857d6a..f04cba1edd 100644
--- a/drape_frontend/shape_view_params.hpp
+++ b/drape_frontend/shape_view_params.hpp
@@ -14,9 +14,9 @@ namespace df
struct CommonViewParams
{
- float m_depth;
- int m_minVisibleScale;
- uint8_t m_rank;
+ float m_depth = 0.0f;
+ int m_minVisibleScale = 0;
+ uint8_t m_rank = 0;
};
struct PoiSymbolViewParams : CommonViewParams
@@ -26,7 +26,7 @@ struct PoiSymbolViewParams : CommonViewParams
FeatureID m_id;
string m_symbolName;
uint32_t m_extendingSize;
- float m_posZ;
+ float m_posZ = 0.0f;
};
struct CircleViewParams : CommonViewParams
@@ -35,29 +35,29 @@ struct CircleViewParams : CommonViewParams
FeatureID m_id;
dp::Color m_color;
- float m_radius;
+ float m_radius = 0.0f;
};
struct AreaViewParams : CommonViewParams
{
dp::Color m_color;
- float m_minPosZ;
- float m_posZ;
+ float m_minPosZ = 0.0f;
+ float m_posZ = 0.0f;
};
struct LineViewParams : CommonViewParams
{
dp::Color m_color;
- float m_width;
+ float m_width = 0.0f;
dp::LineCap m_cap;
dp::LineJoin m_join;
buffer_vector<uint8_t, 8> m_pattern;
- float m_baseGtoPScale;
+ float m_baseGtoPScale = 1.0f;
};
struct TextViewParams : CommonViewParams
{
- TextViewParams() : m_extendingSize(0) {}
+ TextViewParams() {}
FeatureID m_featureID;
dp::FontDecl m_primaryTextFont;
@@ -66,26 +66,28 @@ struct TextViewParams : CommonViewParams
string m_secondaryText;
dp::Anchor m_anchor;
m2::PointF m_primaryOffset;
- bool m_primaryOptional;
- bool m_secondaryOptional;
- uint32_t m_extendingSize;
- float m_posZ;
+ bool m_primaryOptional = false;
+ bool m_secondaryOptional = false;
+ bool m_hasMark = false;
+ uint32_t m_extendingSize = 0;
+ float m_posZ = 0.0f;
};
struct PathTextViewParams : CommonViewParams
{
+ FeatureID m_featureID;
dp::FontDecl m_textFont;
string m_text;
- float m_baseGtoPScale;
+ float m_baseGtoPScale = 1.0f;
};
struct PathSymbolViewParams : CommonViewParams
{
FeatureID m_featureID;
string m_symbolName;
- float m_offset;
- float m_step;
- float m_baseGtoPScale;
+ float m_offset = 0.0f;
+ float m_step = 0.0f;
+ float m_baseGtoPScale = 1.0f;
};
} // namespace df
diff --git a/drape_frontend/stylist.cpp b/drape_frontend/stylist.cpp
index 23e071d833..7a459dd3cc 100644
--- a/drape_frontend/stylist.cpp
+++ b/drape_frontend/stylist.cpp
@@ -199,7 +199,10 @@ void CaptionDescription::Init(FeatureType const & f,
// Mark houses without names/numbers so user can select them by single tap.
if (m_houseNumber.empty() && m_mainText.empty() && ftypes::IsBuildingChecker::Instance()(f))
+ {
m_houseNumber = "ยท";
+ m_hasMark = true;
+ }
SwapCaptions(zoomLevel);
DiscardLongCaption(zoomLevel);
@@ -260,6 +263,11 @@ bool CaptionDescription::IsNameExists() const
return !m_mainText.empty() || !m_houseNumber.empty();
}
+bool CaptionDescription::HasMark() const
+{
+ return m_hasMark;
+}
+
void CaptionDescription::SwapCaptions(int const zoomLevel)
{
if (zoomLevel <= scales::GetUpperWorldScale() && !m_auxText.empty())
diff --git a/drape_frontend/stylist.hpp b/drape_frontend/stylist.hpp
index 2540c68c39..148e78c3cc 100644
--- a/drape_frontend/stylist.hpp
+++ b/drape_frontend/stylist.hpp
@@ -30,6 +30,7 @@ struct CaptionDescription
string const & GetRoadNumber() const;
string GetPathName() const;
bool IsNameExists() const;
+ bool HasMark() const;
private:
void SwapCaptions(int const zoomLevel);
@@ -40,6 +41,7 @@ private:
string m_auxText;
string m_roadNumber;
string m_houseNumber;
+ bool m_hasMark = false;
};
class Stylist
diff --git a/drape_frontend/text_handle.cpp b/drape_frontend/text_handle.cpp
index c38c9322ba..609190153e 100644
--- a/drape_frontend/text_handle.cpp
+++ b/drape_frontend/text_handle.cpp
@@ -2,6 +2,8 @@
#include "drape/texture_manager.hpp"
+#include "base/logging.hpp"
+
namespace df
{
@@ -77,4 +79,13 @@ void TextHandle::SetForceUpdateNormals(bool forceUpdate) const
m_forceUpdateNormals = forceUpdate;
}
+#ifdef DEBUG_OVERLAYS_OUTPUT
+string TextHandle::GetOverlayDebugInfo()
+{
+ ostringstream out;
+ out << "Text Priority(" << GetPriority() << ") " << GetFeatureID().m_index << " " << strings::ToUtf8(m_text);
+ return out.str();
+}
+#endif
+
} // namespace df
diff --git a/drape_frontend/text_handle.hpp b/drape_frontend/text_handle.hpp
index 7524f7eb95..5bbbf023e6 100644
--- a/drape_frontend/text_handle.hpp
+++ b/drape_frontend/text_handle.hpp
@@ -37,6 +37,10 @@ public:
void SetForceUpdateNormals(bool forceUpdate) const;
+#ifdef DEBUG_OVERLAYS_OUTPUT
+ virtual string GetOverlayDebugInfo() override;
+#endif
+
protected:
gpu::TTextDynamicVertexBuffer m_buffer;
mutable bool m_forceUpdateNormals;
diff --git a/drape_frontend/text_layout.cpp b/drape_frontend/text_layout.cpp
index 932509ddc3..d38f88f380 100644
--- a/drape_frontend/text_layout.cpp
+++ b/drape_frontend/text_layout.cpp
@@ -518,17 +518,31 @@ bool PathTextLayout::CacheDynamicGeometry(m2::Spline::iterator const & iter, flo
return true;
}
-// static
-void PathTextLayout::CalculatePositions(vector<float> & offsets, float splineLength,
- float splineScaleToPixel, float textPixelLength)
+float PathTextLayout::CalculateTextLength(float textPixelLength)
{
//we leave a little space on either side of the text that would
//remove the comparison for equality of spline portions
float const kTextBorder = 4.0f;
- float const textLength = kTextBorder + textPixelLength;
+ return kTextBorder + textPixelLength;
+}
+
+bool PathTextLayout::CalculatePerspectivePosition(float splineLength, float textPixelLength, float & offset)
+{
+ float const textLength = CalculateTextLength(textPixelLength);
+ if (textLength > splineLength * 2.0f)
+ return false;
+
+ offset = splineLength * 0.5f;
+ return true;
+}
+
+void PathTextLayout::CalculatePositions(vector<float> & offsets, float splineLength,
+ float splineScaleToPixel, float textPixelLength)
+{
+ float const textLength = CalculateTextLength(textPixelLength);
// on next readable scale m_scaleGtoP will be twice
- if (textLength > splineLength * 2.0 * splineScaleToPixel)
+ if (textLength > splineLength * 2.0f * splineScaleToPixel)
return;
float const kPathLengthScalar = 0.75;
@@ -542,7 +556,7 @@ void PathTextLayout::CalculatePositions(vector<float> & offsets, float splineLen
{
// if we can't place 2 text and empty part on path
// we place only one text on center of path
- offsets.push_back(splineLength / 2.0f);
+ offsets.push_back(splineLength * 0.5f);
}
else
{
diff --git a/drape_frontend/text_layout.hpp b/drape_frontend/text_layout.hpp
index e01918270c..41edeca819 100644
--- a/drape_frontend/text_layout.hpp
+++ b/drape_frontend/text_layout.hpp
@@ -87,9 +87,6 @@ public:
PathTextLayout(strings::UniString const & text,
float fontSize, ref_ptr<dp::TextureManager> textures);
- static void CalculatePositions(vector<float> & offsets, float splineLength,
- float splineScaleToPixel, float textPixelLength);
-
void CacheStaticGeometry(dp::TextureManager::ColorRegion const & colorRegion,
dp::TextureManager::ColorRegion const & outlineRegion,
gpu::TTextOutlinedStaticVertexBuffer & staticBuffer) const;
@@ -101,6 +98,15 @@ public:
float depth,
m2::PointD const & globalPivot,
gpu::TTextDynamicVertexBuffer & buffer) const;
+
+ static bool CalculatePerspectivePosition(float splineLength, float textPixelLength,
+ float & offset);
+
+ static void CalculatePositions(vector<float> & offsets, float splineLength,
+ float splineScaleToPixel, float textPixelLength);
+
+private:
+ static float CalculateTextLength(float textPixelLength);
};
class SharedTextLayout
diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp
index a11a15ee09..38b1da9512 100644
--- a/drape_frontend/text_shape.cpp
+++ b/drape_frontend/text_shape.cpp
@@ -123,11 +123,12 @@ private:
} // namespace
TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params,
- bool hasPOI, bool affectedByZoomPriority)
+ bool hasPOI, size_t textIndex, bool affectedByZoomPriority)
: m_basePoint(basePoint)
, m_params(params)
, m_hasPOI(hasPOI)
, m_affectedByZoomPriority(affectedByZoomPriority)
+ , m_textIndex(textIndex)
{}
void TextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const
@@ -277,16 +278,18 @@ void TextShape::DrawSubStringOutlined(StraightTextLayout const & layout, dp::Fon
uint64_t TextShape::GetOverlayPriority() const
{
- // Overlay priority for text shapes considers the existance of secondary string and length of primary text.
- // - If the text has secondary string then it has more priority;
- // - The more text length, the more priority.
- // [6 bytes - standard overlay priority][1 byte - secondary text][1 byte - length].
+ // Set up minimal priority for marks which substitute texts.
+ if (m_params.m_hasMark)
+ return 0;
+
+ // Overlay priority for text shapes considers length of the primary text
+ // (the more text length, the more priority) and index of text.
+ // [6 bytes - standard overlay priority][1 byte - length][1 byte - text index].
static uint64_t constexpr kMask = ~static_cast<uint64_t>(0xFFFF);
uint64_t priority = dp::CalculateOverlayPriority(m_params.m_minVisibleScale, m_params.m_rank, m_params.m_depth);
priority &= kMask;
- if (!m_params.m_secondaryText.empty())
- priority |= 0xFF00;
- priority |= (0xFF - static_cast<uint8_t>(m_params.m_primaryText.size()));
+ priority |= (static_cast<uint8_t>(m_params.m_primaryText.size()) << 8);
+ priority |= static_cast<uint8_t>(m_textIndex);
return priority;
}
diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp
index cceef289c0..e95466245b 100644
--- a/drape_frontend/text_shape.hpp
+++ b/drape_frontend/text_shape.hpp
@@ -15,10 +15,10 @@ class TextShape : public MapShape
{
public:
TextShape(m2::PointF const & basePoint, TextViewParams const & params,
- bool hasPOI, bool affectedByZoomPriority = true);
+ bool hasPOI, size_t textIndex, bool affectedByZoomPriority);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
- MapShapePriority GetPriority() const override { return MapShapePriority::TextAndPoiPriority; }
+ MapShapeType GetType() const override { return MapShapeType::OverlayType; }
private:
void DrawSubString(StraightTextLayout const & layout, dp::FontDecl const & font,
@@ -38,6 +38,7 @@ private:
TextViewParams m_params;
bool m_hasPOI;
bool m_affectedByZoomPriority;
+ size_t m_textIndex;
};
} // namespace df
diff --git a/drape_head/testing_engine.cpp b/drape_head/testing_engine.cpp
index 2e5f60bc91..d4cbdebbac 100644
--- a/drape_head/testing_engine.cpp
+++ b/drape_head/testing_engine.cpp
@@ -442,7 +442,7 @@ void TestingEngine::DrawImpl()
params.m_primaryOffset = m2::PointF(12.0, 20.0);
params.m_primaryOptional = true;
params.m_secondaryOptional = true;
- TextShape sh1(m2::PointF(82.277071f, 46.9271164f), params, false);
+ TextShape sh1(m2::PointF(82.277071f, 46.9271164f), params, false, 0, true);
sh1.Draw(make_ref(m_batcher), make_ref(m_textures));
vector<m2::PointD> path;
diff --git a/geometry/screenbase.cpp b/geometry/screenbase.cpp
index c00f882b86..b46a6da78c 100644
--- a/geometry/screenbase.cpp
+++ b/geometry/screenbase.cpp
@@ -411,3 +411,15 @@ m2::PointD ScreenBase::P3dtoP(m2::PointD const & pt) const
return pixelPointOriginal;
}
+
+bool ScreenBase::IsReverseProjection3d(m2::PointD const & pt) const
+{
+ if (!m_isPerspective)
+ return false;
+
+ Vector3dT const normalizedPoint{float(2.0 * pt.x / m_PixelRect.SizeX() - 1.0),
+ -float(2.0 * pt.y / m_PixelRect.SizeY() - 1.0), 0.0, 1.0};
+
+ Vector3dT const perspectivePoint = normalizedPoint * m_Pto3d;
+ return perspectivePoint(0, 3) < 0.0;
+}
diff --git a/geometry/screenbase.hpp b/geometry/screenbase.hpp
index 016feab973..93959d9998 100644
--- a/geometry/screenbase.hpp
+++ b/geometry/screenbase.hpp
@@ -139,6 +139,8 @@ public:
Matrix3dT const & Pto3dMatrix() const { return m_Pto3d; }
bool isPerspective() const { return m_isPerspective; }
+ bool IsReverseProjection3d(m2::PointD const & pt) const;
+
m2::PointD PtoP3d(m2::PointD const & pt) const;
m2::PointD PtoP3d(m2::PointD const & pt, double ptZ) const;