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>2015-11-11 16:27:18 +0300
committerr.kuznetsov <r.kuznetsov@corp.mail.ru>2015-11-30 16:28:02 +0300
commitab4887c6c9f44bf6fe60dba36e4c5dfa13676a4b (patch)
tree61e51364da9def753634f1dbdcda4ad56ff60ed6
parent2e5a22737248bcdad96d5c0f1f3b11c961039619 (diff)
Overlay binding
-rw-r--r--drape/overlay_handle.cpp1
-rw-r--r--drape/overlay_handle.hpp16
-rw-r--r--drape/overlay_tree.cpp143
-rw-r--r--drape/overlay_tree.hpp10
-rw-r--r--drape_frontend/apply_feature_functors.cpp43
-rw-r--r--drape_frontend/shape_view_params.hpp2
-rw-r--r--drape_frontend/text_shape.cpp30
-rw-r--r--drape_frontend/text_shape.hpp5
-rw-r--r--drape_head/testing_engine.cpp4
-rw-r--r--geometry/tree4d.hpp10
10 files changed, 200 insertions, 64 deletions
diff --git a/drape/overlay_handle.cpp b/drape/overlay_handle.cpp
index 8542b3f63b..82600471f2 100644
--- a/drape/overlay_handle.cpp
+++ b/drape/overlay_handle.cpp
@@ -23,6 +23,7 @@ OverlayHandle::OverlayHandle(FeatureID const & id, dp::Anchor anchor, uint64_t p
: m_id(id)
, m_anchor(anchor)
, m_priority(priority)
+ , m_overlayRank(OverlayRank0)
, m_isVisible(false)
{
}
diff --git a/drape/overlay_handle.hpp b/drape/overlay_handle.hpp
index 5e487ec47c..ffc7f56bf8 100644
--- a/drape/overlay_handle.hpp
+++ b/drape/overlay_handle.hpp
@@ -17,6 +17,15 @@
namespace dp
{
+enum OverlayRank
+{
+ OverlayRank0 = 0,
+ OverlayRank1,
+ OverlayRank2,
+
+ OverlayRanksCount
+};
+
class OverlayHandle
{
public:
@@ -50,11 +59,18 @@ public:
FeatureID const & GetFeatureID() const;
uint64_t const & GetPriority() const;
+ virtual bool IsBound() const { return false; }
+
+ int GetOverlayRank() const { return m_overlayRank; }
+ void SetOverlayRank(int overlayRank) { m_overlayRank = overlayRank; }
+
protected:
FeatureID const m_id;
dp::Anchor const m_anchor;
uint64_t const m_priority;
+ int m_overlayRank;
+
typedef pair<BindingInfo, MutateRegion> TOffsetNode;
TOffsetNode const & GetOffsetNode(uint8_t bufferID) const;
diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp
index b7e85af9c9..57e0cec621 100644
--- a/drape/overlay_tree.cpp
+++ b/drape/overlay_tree.cpp
@@ -7,7 +7,9 @@ namespace dp
{
int const kFrameUpdarePeriod = 10;
-int const kAverageHandlesCount = 500;
+int const kAverageHandlesCount[dp::OverlayRanksCount] = { 300, 200, 100 };
+
+using TOverlayContainer = buffer_vector<detail::OverlayInfo, 8>;
namespace
{
@@ -16,21 +18,26 @@ class HandleComparator
{
public:
bool operator()(OverlayTree::THandle const & l, OverlayTree::THandle const & r) const
+ {
+ return IsGreater(l.first, r.first);
+ }
+
+ bool IsGreater(ref_ptr<OverlayHandle> const & l, ref_ptr<OverlayHandle> const & r) const
{
- uint64_t const priorityLeft = l.first->GetPriority();
- uint64_t const priorityRight = r.first->GetPriority();
+ uint64_t const priorityLeft = l->GetPriority();
+ uint64_t const priorityRight = r->GetPriority();
if (priorityLeft > priorityRight)
return true;
if (priorityLeft == priorityRight)
{
- auto const & hashLeft = l.first->GetFeatureID();
- auto const & hashRight = r.first->GetFeatureID();
+ auto const & hashLeft = l->GetFeatureID();
+ auto const & hashRight = r->GetFeatureID();
if (hashLeft < hashRight)
return true;
if (hashLeft == hashRight)
- return l.first.get() < r.first.get();
+ return l.get() < r.get();
}
return false;
@@ -42,7 +49,8 @@ public:
OverlayTree::OverlayTree()
: m_frameCounter(-1)
{
- m_handles.reserve(kAverageHandlesCount);
+ for (size_t i = 0; i < m_handles.size(); i++)
+ m_handles[i].reserve(kAverageHandlesCount[i]);
}
void OverlayTree::Frame()
@@ -86,39 +94,60 @@ void OverlayTree::Add(ref_ptr<OverlayHandle> handle, bool isTransparent)
return;
}
- m_handles.emplace_back(make_pair(handle, isTransparent));
+ int const rank = handle->GetOverlayRank();
+ ASSERT_LESS(rank, m_handles.size(), ());
+ m_handles[rank].emplace_back(make_pair(handle, isTransparent));
}
-void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle, bool isTransparent)
+void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle, bool isTransparent,
+ detail::OverlayInfo const & parentOverlay)
{
ScreenBase const & modelView = GetModelView();
m2::RectD const pixelRect = handle->GetPixelRect(modelView);
- typedef buffer_vector<detail::OverlayInfo, 8> OverlayContainerT;
- OverlayContainerT elements;
- /*
- * Find elements that already on OverlayTree and it's pixel rect
- * intersect with handle pixel rect ("Intersected elements")
- */
+ TOverlayContainer elements;
+
+ // Find elements that already on OverlayTree and it's pixel rect
+ // intersect with handle pixel rect ("Intersected elements").
ForEachInRect(pixelRect, [&] (detail::OverlayInfo const & info)
{
- if (isTransparent == info.m_isTransparent && handle->IsIntersect(modelView, info.m_handle))
+ bool const isParent = (info == parentOverlay);
+ if (!isParent && isTransparent == info.m_isTransparent &&
+ handle->IsIntersect(modelView, info.m_handle))
elements.push_back(info);
});
- double const inputPriority = handle->GetPriority();
- /*
- * 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 (OverlayContainerT::const_iterator it = elements.begin(); it != elements.end(); ++it)
- if (inputPriority < it->m_handle->GetPriority())
+ 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;
+
+ // 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;
+ for (auto const & info : elements)
+ {
+ if (comparator.IsGreater(info.m_handle, handleToCompare))
+ {
+ // Handle is displaced and bound to its parent, parent will be displaced too.
+ if (boundToParent)
+ Erase(parentOverlay);
return;
+ }
+ }
+
+ // Current overlay displaces other overlay, delete them.
+ for (auto const & info : elements)
+ AddHandleToDelete(info);
+
+ for (auto const & handle : m_handlesToDelete)
+ Erase(handle);
- for (OverlayContainerT::const_iterator it = elements.begin(); it != elements.end(); ++it)
- Erase(*it);
+ m_handlesToDelete.clear();
TBase::Add(detail::OverlayInfo(handle, isTransparent), pixelRect);
}
@@ -126,10 +155,21 @@ void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle, bool isTransparent
void OverlayTree::EndOverlayPlacing()
{
HandleComparator comparator;
- sort(m_handles.begin(), m_handles.end(), comparator);
- for (auto const & handle : m_handles)
- InsertHandle(handle.first, handle.second);
- m_handles.clear();
+
+ 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;
+ if (!CheckHandle(handle.first, rank, parentOverlay))
+ continue;
+
+ InsertHandle(handle.first, handle.second, parentOverlay);
+ }
+
+ m_handles[rank].clear();
+ }
ForEach([] (detail::OverlayInfo const & info)
{
@@ -137,6 +177,47 @@ void OverlayTree::EndOverlayPlacing()
});
}
+bool OverlayTree::CheckHandle(ref_ptr<OverlayHandle> handle, int currentRank,
+ detail::OverlayInfo & parentOverlay)
+{
+ if (currentRank == dp::OverlayRank0)
+ return true;
+
+ int const seachingRank = currentRank - 1;
+ return FindNode([&](detail::OverlayInfo const & info) -> bool
+ {
+ if (info.m_handle->GetFeatureID() == handle->GetFeatureID() &&
+ info.m_handle->GetOverlayRank() == seachingRank)
+ {
+ parentOverlay = info;
+ return true;
+ }
+ return false;
+ });
+}
+
+void OverlayTree::AddHandleToDelete(detail::OverlayInfo const & overlay)
+{
+ if (overlay.m_handle->IsBound())
+ {
+ ForEach([&](detail::OverlayInfo const & info)
+ {
+ if (info.m_handle->GetFeatureID() == overlay.m_handle->GetFeatureID())
+ {
+ if (find(m_handlesToDelete.begin(),
+ m_handlesToDelete.end(), info) == m_handlesToDelete.end())
+ m_handlesToDelete.push_back(info);
+ }
+ });
+ }
+ else
+ {
+ if (find(m_handlesToDelete.begin(),
+ m_handlesToDelete.end(), overlay) == m_handlesToDelete.end())
+ m_handlesToDelete.push_back(overlay);
+ }
+}
+
void OverlayTree::Select(m2::RectD const & rect, TSelectResult & result) const
{
ScreenBase screen = m_traits.m_modelView;
diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp
index 9e617dff3a..093016a484 100644
--- a/drape/overlay_tree.hpp
+++ b/drape/overlay_tree.hpp
@@ -7,6 +7,7 @@
#include "base/buffer_vector.hpp"
+#include "std/array.hpp"
#include "std/vector.hpp"
namespace dp
@@ -66,10 +67,15 @@ public:
private:
ScreenBase const & GetModelView() const { return m_traits.m_modelView; }
- void InsertHandle(ref_ptr<OverlayHandle> handle, bool isTransparent);
+ void InsertHandle(ref_ptr<OverlayHandle> handle, bool isTransparent,
+ detail::OverlayInfo const & parentOverlay);
+ bool CheckHandle(ref_ptr<OverlayHandle> handle, int currentRank,
+ detail::OverlayInfo & parentOverlay);
+ void AddHandleToDelete(detail::OverlayInfo const & overlay);
int m_frameCounter;
- vector<THandle> m_handles;
+ array<vector<THandle>, dp::OverlayRanksCount> m_handles;
+ vector<detail::OverlayInfo> m_handlesToDelete;
};
} // namespace dp
diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp
index 386fe59963..b09dfde51e 100644
--- a/drape_frontend/apply_feature_functors.cpp
+++ b/drape_frontend/apply_feature_functors.cpp
@@ -220,6 +220,8 @@ void BaseApplyFeature::ExtractCaptionParams(CaptionDefProto const * primaryProto
params.m_primaryText = m_captions.GetMainText();
params.m_primaryTextFont = decl;
params.m_primaryOffset = GetOffset(primaryProto);
+ params.m_primaryOptional = primaryProto->is_optional();
+ params.m_secondaryOptional = true;
if (secondaryProto)
{
@@ -228,6 +230,7 @@ void BaseApplyFeature::ExtractCaptionParams(CaptionDefProto const * primaryProto
params.m_secondaryText = m_captions.GetAuxText();
params.m_secondaryTextFont = auxDecl;
+ params.m_secondaryOptional = secondaryProto->is_optional();
}
}
@@ -252,33 +255,35 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule)
{
if (m_hasPoint == false)
return;
- drule::BaseRule const * pRule = rule.first;
- float depth = rule.second;
- bool isNode = (pRule->GetType() & drule::node) != 0;
- CaptionDefProto const * capRule = pRule->GetCaption(0);
- if (capRule && isNode)
- {
- TextViewParams params;
- ExtractCaptionParams(capRule, pRule->GetCaption(1), depth, params);
- params.m_minVisibleScale = m_minVisibleScale;
- params.m_rank = m_rank;
- if(!params.m_primaryText.empty() || !params.m_secondaryText.empty())
- m_insertShape(make_unique_dp<TextShape>(m_centerPoint, params));
- }
+ drule::BaseRule const * pRule = rule.first;
+ float const depth = rule.second;
SymbolRuleProto const * symRule = pRule->GetSymbol();
- if (symRule)
+ if (symRule != nullptr)
{
m_symbolDepth = depth;
- m_symbolRule = symRule;
+ m_symbolRule = symRule;
}
CircleRuleProto const * circleRule = pRule->GetCircle();
- if (circleRule)
+ if (circleRule != nullptr)
{
m_circleDepth = depth;
- m_circleRule = circleRule;
+ m_circleRule = circleRule;
+ }
+
+ bool const hasPOI = (m_symbolRule != nullptr || m_circleRule != nullptr);
+ bool const isNode = (pRule->GetType() & drule::node) != 0;
+ CaptionDefProto const * capRule = pRule->GetCaption(0);
+ if (capRule && isNode)
+ {
+ TextViewParams params;
+ ExtractCaptionParams(capRule, pRule->GetCaption(1), depth, params);
+ params.m_minVisibleScale = m_minVisibleScale;
+ params.m_rank = m_rank;
+ if(!params.m_primaryText.empty() || !params.m_secondaryText.empty())
+ m_insertShape(make_unique_dp<TextShape>(m_centerPoint, params, hasPOI));
}
}
@@ -501,11 +506,13 @@ void ApplyLineFeature::Finish()
viewParams.m_primaryText = roadNumber;
viewParams.m_primaryTextFont = font;
viewParams.m_primaryOffset = m2::PointF(0, 0);
+ viewParams.m_primaryOptional = true;
+ viewParams.m_secondaryOptional = true;
m2::Spline::iterator it = m_spline.CreateIterator();
while (!it.BeginAgain())
{
- m_insertShape(make_unique_dp<TextShape>(it.m_pos, viewParams));
+ m_insertShape(make_unique_dp<TextShape>(it.m_pos, viewParams, false /* hasPOI */));
it.Advance(splineStep);
}
}
diff --git a/drape_frontend/shape_view_params.hpp b/drape_frontend/shape_view_params.hpp
index b6b85d8796..e100160140 100644
--- a/drape_frontend/shape_view_params.hpp
+++ b/drape_frontend/shape_view_params.hpp
@@ -60,6 +60,8 @@ struct TextViewParams : CommonViewParams
string m_secondaryText;
dp::Anchor m_anchor;
m2::PointF m_primaryOffset;
+ bool m_primaryOptional;
+ bool m_secondaryOptional;
};
struct PathTextViewParams : CommonViewParams
diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp
index d30b863f78..65778c76fc 100644
--- a/drape_frontend/text_shape.cpp
+++ b/drape_frontend/text_shape.cpp
@@ -27,11 +27,12 @@ public:
dp::Anchor anchor, glsl::vec2 const & pivot,
glsl::vec2 const & pxSize, glsl::vec2 const & offset,
uint64_t priority, ref_ptr<dp::TextureManager> textureManager,
- gpu::TTextDynamicVertexBuffer && normals)
+ bool isOptional, gpu::TTextDynamicVertexBuffer && normals)
: TextHandle(id, text, anchor, priority, textureManager, move(normals))
, m_pivot(glsl::ToPoint(pivot))
, m_offset(glsl::ToPoint(offset))
, m_size(glsl::ToPoint(pxSize))
+ , m_isOptional(isOptional)
{}
m2::RectD GetPixelRect(ScreenBase const & screen) const override
@@ -70,17 +71,24 @@ public:
rects.push_back(m2::RectF(GetPixelRect(screen)));
}
+ bool IsBound() const override
+ {
+ return !m_isOptional;
+ }
+
private:
m2::PointF m_pivot;
m2::PointF m_offset;
m2::PointF m_size;
+ bool m_isOptional;
};
} // namespace
-TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params)
+TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params, bool hasPOI)
: m_basePoint(basePoint),
- m_params(params)
+ m_params(params),
+ m_hasPOI(hasPOI)
{}
void TextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const
@@ -108,18 +116,18 @@ void TextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> t
}
if (secondaryLayout.GetGlyphCount() > 0)
- DrawSubString(secondaryLayout, m_params.m_secondaryTextFont, secondaryOffset, batcher, textures);
+ DrawSubString(secondaryLayout, m_params.m_secondaryTextFont, secondaryOffset, batcher,
+ textures, false /* isPrimary */, m_params.m_secondaryOptional);
}
if (primaryLayout.GetGlyphCount() > 0)
- DrawSubString(primaryLayout, m_params.m_primaryTextFont, primaryOffset, batcher, textures);
+ DrawSubString(primaryLayout, m_params.m_primaryTextFont, primaryOffset, batcher,
+ textures, true /* isPrimary */, m_params.m_primaryOptional);
}
-void TextShape::DrawSubString(StraightTextLayout const & layout,
- dp::FontDecl const & font,
- glsl::vec2 const & baseOffset,
- ref_ptr<dp::Batcher> batcher,
- ref_ptr<dp::TextureManager> textures) const
+void TextShape::DrawSubString(StraightTextLayout const & layout, dp::FontDecl const & font,
+ glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
+ ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const
{
gpu::TTextStaticVertexBuffer staticBuffer;
gpu::TTextDynamicVertexBuffer dynamicBuffer;
@@ -150,7 +158,9 @@ void TextShape::DrawSubString(StraightTextLayout const & layout,
baseOffset,
GetOverlayPriority(),
textures,
+ isOptional,
move(dynamicBuffer));
+ handle->SetOverlayRank(m_hasPOI ? (isPrimary ? dp::OverlayRank1 : dp::OverlayRank2) : dp::OverlayRank0);
dp::AttributeProvider provider(2, staticBuffer.size());
provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data()));
diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp
index 01c6d33cf2..06d4cf9043 100644
--- a/drape_frontend/text_shape.hpp
+++ b/drape_frontend/text_shape.hpp
@@ -14,7 +14,7 @@ class StraightTextLayout;
class TextShape : public MapShape
{
public:
- TextShape(m2::PointF const & basePoint, TextViewParams const & params);
+ TextShape(m2::PointF const & basePoint, TextViewParams const & params, bool hasPOI);
void Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const override;
MapShapePriority GetPriority() const override { return MapShapePriority::TextAndPoiPriority; }
@@ -22,12 +22,13 @@ public:
private:
void DrawSubString(StraightTextLayout const & layout, dp::FontDecl const & font,
glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
- ref_ptr<dp::TextureManager> textures) const;
+ ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const;
uint64_t GetOverlayPriority() const;
m2::PointF m_basePoint;
TextViewParams m_params;
+ bool m_hasPOI;
};
} // namespace df
diff --git a/drape_head/testing_engine.cpp b/drape_head/testing_engine.cpp
index 2b31921ce3..a7fdc82117 100644
--- a/drape_head/testing_engine.cpp
+++ b/drape_head/testing_engine.cpp
@@ -440,7 +440,9 @@ void TestingEngine::DrawImpl()
params.m_secondaryTextFont = auxFd;
params.m_secondaryText = "Народная Китайская республика";
params.m_primaryOffset = m2::PointF(12.0, 20.0);
- TextShape sh1(m2::PointF(82.277071f, 46.9271164f), params);
+ params.m_primaryOptional = true;
+ params.m_secondaryOptional = true;
+ TextShape sh1(m2::PointF(82.277071f, 46.9271164f), params, false);
sh1.Draw(make_ref(m_batcher), make_ref(m_textures));
vector<m2::PointD> path;
diff --git a/geometry/tree4d.hpp b/geometry/tree4d.hpp
index 3b9ee92f1f..3d25a1f6b5 100644
--- a/geometry/tree4d.hpp
+++ b/geometry/tree4d.hpp
@@ -227,6 +227,16 @@ namespace m4
}
template <class ToDo>
+ bool FindNode(ToDo toDo) const
+ {
+ for (ValueT const & v : m_tree)
+ if (toDo(v.m_val))
+ return true;
+
+ return false;
+ }
+
+ template <class ToDo>
void ForEachWithRect(ToDo toDo) const
{
for (ValueT const & v : m_tree)