diff --git a/drape/drape.pro b/drape/drape.pro index 592d58512b..63af30a72c 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -22,6 +22,9 @@ OTHER_FILES += \ shaders/arrow3d_vertex_shader.vsh \ shaders/circle_shader.fsh \ shaders/circle_shader.vsh \ + shaders/colored_symbol_billboard_shader.vsh \ + shaders/colored_symbol_shader.fsh \ + shaders/colored_symbol_shader.vsh \ shaders/compass_vertex_shader.vsh \ shaders/dashed_fragment_shader.fsh \ shaders/dashed_vertex_shader.vsh \ diff --git a/drape/drape_diagnostics.hpp b/drape/drape_diagnostics.hpp index d8fc2a5a9b..5948407a92 100644 --- a/drape/drape_diagnostics.hpp +++ b/drape/drape_diagnostics.hpp @@ -3,6 +3,7 @@ //#define DRAW_TILE_NET //#define RENDER_DEBUG_RECTS //#define COLLECT_DISPLACEMENT_INFO +//#define DEBUG_OVERLAYS_OUTPUT //#define DRAPE_MEASURER //#define SCENARIO_ENABLE diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp index 3defee00f3..efe2cecfdb 100644 --- a/drape/glyph_manager.cpp +++ b/drape/glyph_manager.cpp @@ -65,8 +65,6 @@ namespace dp namespace { -uint32_t const kSdfBorder = 4; -double const kNonSdfBorder = 0.2; int const kInvalidFont = -1; template @@ -203,7 +201,6 @@ public: SharedBufferManager::shared_buffer_ptr_t data; uint32_t imageWidth = bitmap.width; uint32_t imageHeight = bitmap.rows; - int border = 0; if (bitmap.buffer != nullptr) { if (isSdf) @@ -218,7 +215,7 @@ public: } else { - border = glyphHeight * kNonSdfBorder; + int const border = kSdfBorder; imageHeight += 2 * border; imageWidth += 2 * border; @@ -248,8 +245,8 @@ public: { static_cast(glyph->advance.x >> 16) * scale, static_cast(glyph->advance.y >> 16) * scale, - static_cast(bbox.xMin) * scale + border, - static_cast(bbox.yMin) * scale + border, + static_cast(bbox.xMin) * scale, + static_cast(bbox.yMin) * scale, true }; diff --git a/drape/glyph_manager.hpp b/drape/glyph_manager.hpp index 5af16cf1e4..fbbacf19d7 100644 --- a/drape/glyph_manager.hpp +++ b/drape/glyph_manager.hpp @@ -12,6 +12,8 @@ namespace dp { +uint32_t constexpr kSdfBorder = 4; + struct UnicodeBlock; class GlyphManager diff --git a/drape/overlay_handle.cpp b/drape/overlay_handle.cpp index f2e090326d..2bf1df8fa0 100644 --- a/drape/overlay_handle.cpp +++ b/drape/overlay_handle.cpp @@ -24,7 +24,7 @@ private: uint8_t m_bufferID; }; -OverlayHandle::OverlayHandle(FeatureID const & id, dp::Anchor anchor, +OverlayHandle::OverlayHandle(OverlayID const & id, dp::Anchor anchor, uint64_t priority, bool isBillboard) : m_id(id) , m_anchor(anchor) @@ -126,7 +126,7 @@ void OverlayHandle::AddDynamicAttribute(BindingInfo const & binding, uint32_t of m_offsets.insert(make_pair(binding, MutateRegion(offset, count))); } -FeatureID const & OverlayHandle::GetFeatureID() const +OverlayID const & OverlayHandle::GetOverlayID() const { return m_id; } @@ -199,7 +199,7 @@ uint64_t OverlayHandle::GetPriorityInFollowingMode() const { return GetPriority(); } -SquareHandle::SquareHandle(FeatureID const & id, dp::Anchor anchor, m2::PointD const & gbPivot, +SquareHandle::SquareHandle(OverlayID const & id, dp::Anchor anchor, m2::PointD const & gbPivot, m2::PointD const & pxSize, uint64_t priority, bool isBound, string const & debugStr, bool isBillboard) : TBase(id, anchor, priority, isBillboard) @@ -244,7 +244,7 @@ bool SquareHandle::IsBound() const { return m_isBound; } string SquareHandle::GetOverlayDebugInfo() { ostringstream out; - out << "POI Priority(" << GetPriority() << ") " << GetFeatureID().m_index << " " << m_debugStr; + out << "POI Priority(" << GetPriority() << ") " << GetOverlayID().m_featureId.m_index << " " << m_debugStr; return out.str(); } #endif diff --git a/drape/overlay_handle.hpp b/drape/overlay_handle.hpp index 725a82d44d..67b6419714 100644 --- a/drape/overlay_handle.hpp +++ b/drape/overlay_handle.hpp @@ -1,5 +1,6 @@ #pragma once +#include "drape/drape_diagnostics.hpp" #include "drape/drape_global.hpp" #include "drape/binding_info.hpp" #include "drape/index_buffer_mutator.hpp" @@ -19,8 +20,6 @@ namespace dp { -//#define DEBUG_OVERLAYS_OUTPUT - enum OverlayRank { OverlayRank0 = 0, @@ -36,12 +35,62 @@ uint64_t constexpr kPriorityMaskRank = 0x0000000000FFFFFF; uint64_t constexpr kPriorityMaskAll = kPriorityMaskZoomLevel | kPriorityMaskManual | kPriorityMaskRank; + +struct OverlayID +{ + FeatureID m_featureId; + m2::PointI m_tileCoords; + uint32_t m_index; + + OverlayID(FeatureID const & featureId) + : m_featureId(featureId), m_tileCoords(-1, -1), m_index(0) + {} + OverlayID(FeatureID const & featureId, m2::PointI const & tileCoords, uint32_t index) + : m_featureId(featureId), m_tileCoords(tileCoords), m_index(index) + {} + + bool operator==(OverlayID const & overlayId) const + { + return m_featureId == overlayId.m_featureId && m_tileCoords == overlayId.m_tileCoords && + m_index == overlayId.m_index; + } + + bool operator!=(OverlayID const & overlayId) const + { + return !operator ==(overlayId); + } + + bool operator<(OverlayID const & overlayId) const + { + if (m_featureId == overlayId.m_featureId) + { + if (m_tileCoords == overlayId.m_tileCoords) + return m_index < overlayId.m_index; + + return m_tileCoords < overlayId.m_tileCoords; + } + return m_featureId < overlayId.m_featureId; + } + + bool operator>(OverlayID const & overlayId) const + { + if (m_featureId == overlayId.m_featureId) + { + if (m_tileCoords == overlayId.m_tileCoords) + return m_index > overlayId.m_index; + + return !(m_tileCoords < overlayId.m_tileCoords); + } + return !(m_featureId < overlayId.m_featureId); + } +}; + class OverlayHandle { public: typedef vector Rects; - OverlayHandle(FeatureID const & id, dp::Anchor anchor, + OverlayHandle(OverlayID const & id, dp::Anchor anchor, uint64_t priority, bool isBillboard); virtual ~OverlayHandle() {} @@ -76,7 +125,7 @@ public: bool HasDynamicAttributes() const; void AddDynamicAttribute(BindingInfo const & binding, uint32_t offset, uint32_t count); - FeatureID const & GetFeatureID() const; + OverlayID const & GetOverlayID() const; uint64_t const & GetPriority() const; virtual uint64_t GetPriorityMask() const { return kPriorityMaskAll; } @@ -100,7 +149,7 @@ public: #endif protected: - FeatureID const m_id; + OverlayID const m_id; dp::Anchor const m_anchor; uint64_t const m_priority; @@ -144,7 +193,7 @@ class SquareHandle : public OverlayHandle using TBase = OverlayHandle; public: - SquareHandle(FeatureID const & id, dp::Anchor anchor, m2::PointD const & gbPivot, + SquareHandle(OverlayID const & id, dp::Anchor anchor, m2::PointD const & gbPivot, m2::PointD const & pxSize, uint64_t priority, bool isBound, string const & debugStr, bool isBillboard = false); diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp index 41e9eb8233..fc4c4637c5 100644 --- a/drape/overlay_tree.cpp +++ b/drape/overlay_tree.cpp @@ -41,14 +41,14 @@ public: if (priorityLeft == priorityRight) { - auto const & hashLeft = l->GetFeatureID(); - auto const & hashRight = r->GetFeatureID(); + auto const & hashLeft = l->GetOverlayID(); + auto const & hashRight = r->GetOverlayID(); - if (hashLeft < hashRight) + if (hashLeft > hashRight) return true; if (hashLeft == hashRight) - return l.get() < r.get(); + return l.get() > r.get(); } return false; @@ -160,7 +160,7 @@ void OverlayTree::Add(ref_ptr handle) m_handles[rank].emplace_back(handle); } -void OverlayTree::InsertHandle(ref_ptr handle, +void OverlayTree::InsertHandle(ref_ptr handle, int currentRank, ref_ptr const & parentOverlay) { ASSERT(IsNeedUpdate(), ()); @@ -188,7 +188,7 @@ void OverlayTree::InsertHandle(ref_ptr handle, ForEachInRect(pixelRect, [&] (ref_ptr const & h) { bool const isParent = (h == parentOverlay) || - (h->GetFeatureID() == handle->GetFeatureID() && + (h->GetOverlayID() == handle->GetOverlayID() && h->GetOverlayRank() < handle->GetOverlayRank()); if (!isParent && handle->IsIntersect(modelView, h)) rivals.push_back(h); @@ -200,7 +200,8 @@ void OverlayTree::InsertHandle(ref_ptr handle, if (boundToParent) handleToCompare = parentOverlay; - bool const selected = m_selectedFeatureID.IsValid() && (handleToCompare->GetFeatureID() == m_selectedFeatureID); + bool const selected = m_selectedFeatureID.IsValid() && + handleToCompare->GetOverlayID().m_featureId == m_selectedFeatureID; if (!selected) { @@ -210,7 +211,8 @@ void OverlayTree::InsertHandle(ref_ptr handle, // But if some of already inserted elements have more priority, then we don't insert "handle". for (auto const & rivalHandle : rivals) { - bool const rejectBySelected = m_selectedFeatureID.IsValid() && (rivalHandle->GetFeatureID() == m_selectedFeatureID); + bool const rejectBySelected = m_selectedFeatureID.IsValid() && + rivalHandle->GetOverlayID().m_featureId == m_selectedFeatureID; bool rejectByDepth = false; if (!rejectBySelected && modelView.isPerspective()) @@ -225,7 +227,7 @@ void OverlayTree::InsertHandle(ref_ptr handle, // Handle is displaced and bound to its parent, parent will be displaced too. if (boundToParent) { - DeleteHandle(parentOverlay); + DeleteHandleWithParents(parentOverlay, currentRank - 1); #ifdef DEBUG_OVERLAYS_OUTPUT LOG(LINFO, ("Displace (0):", handle->GetOverlayDebugInfo(), "->", parentOverlay->GetOverlayDebugInfo())); @@ -260,7 +262,7 @@ void OverlayTree::InsertHandle(ref_ptr handle, // Delete rival handle and all handles bound to it. for (auto it = m_handlesCache.begin(); it != m_handlesCache.end();) { - if ((*it)->GetFeatureID() == rivalHandle->GetFeatureID()) + if ((*it)->GetOverlayID() == rivalHandle->GetOverlayID()) { Erase(*it); @@ -321,7 +323,7 @@ void OverlayTree::EndOverlayPlacing() if (!CheckHandle(handle, rank, parentOverlay)) continue; - InsertHandle(handle, parentOverlay); + InsertHandle(handle, rank, parentOverlay); } } @@ -347,18 +349,20 @@ bool OverlayTree::CheckHandle(ref_ptr handle, int currentRank, if (currentRank == dp::OverlayRank0) return true; - int const seachingRank = currentRank - 1; - for (auto const & h : m_handles[seachingRank]) - { - if (h->GetFeatureID() == handle->GetFeatureID() && - m_handlesCache.find(h) != m_handlesCache.end()) - { - parentOverlay = h; - return true; - } - } + parentOverlay = FindParent(handle, currentRank - 1); + return parentOverlay != nullptr; +} - return false; +ref_ptr OverlayTree::FindParent(ref_ptr handle, int searchingRank) const +{ + ASSERT_GREATER_OR_EQUAL(searchingRank, 0, ()); + ASSERT_LESS(searchingRank, static_cast(m_handles.size()), ()); + for (auto const & h : m_handles[searchingRank]) + { + if (h->GetOverlayID() == handle->GetOverlayID() && m_handlesCache.find(h) != m_handlesCache.end()) + return h; + } + return nullptr; } void OverlayTree::DeleteHandle(ref_ptr const & handle) @@ -368,6 +372,19 @@ void OverlayTree::DeleteHandle(ref_ptr const & handle) Erase(handle); } +void OverlayTree::DeleteHandleWithParents(ref_ptr handle, int currentRank) +{ + currentRank--; + while(currentRank >= dp::OverlayRank0) + { + auto parent = FindParent(handle, currentRank); + if (parent != nullptr && parent->IsBound()) + DeleteHandle(parent); + currentRank--; + } + DeleteHandle(handle); +} + bool OverlayTree::GetSelectedFeatureRect(ScreenBase const & screen, m2::RectD & featureRect) { if (!m_selectedFeatureID.IsValid()) @@ -376,7 +393,7 @@ bool OverlayTree::GetSelectedFeatureRect(ScreenBase const & screen, m2::RectD & featureRect.MakeEmpty(); for (auto const & handle : m_handlesCache) { - if (handle->IsVisible() && handle->GetFeatureID() == m_selectedFeatureID) + if (handle->IsVisible() && handle->GetOverlayID().m_featureId == m_selectedFeatureID) { m2::RectD rect = handle->GetPixelRect(screen, screen.isPerspective()); featureRect.Add(rect); @@ -406,7 +423,7 @@ void OverlayTree::Select(m2::RectD const & rect, TOverlayContainer & result) con ScreenBase screen = m_traits.m_modelView; ForEachInRect(rect, [&](ref_ptr const & h) { - if (!h->HasLinearFeatureShape() && h->IsVisible() && h->GetFeatureID().IsValid()) + if (!h->HasLinearFeatureShape() && h->IsVisible() && h->GetOverlayID().m_featureId.IsValid()) { OverlayHandle::Rects shape; h->GetPixelShape(screen, screen.isPerspective(), shape); diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp index 061540efb3..9f9818a3f1 100644 --- a/drape/overlay_tree.hpp +++ b/drape/overlay_tree.hpp @@ -83,12 +83,15 @@ public: private: ScreenBase const & GetModelView() const { return m_traits.m_modelView; } - void InsertHandle(ref_ptr handle, + void InsertHandle(ref_ptr handle, int currentRank, ref_ptr const & parentOverlay); bool CheckHandle(ref_ptr handle, int currentRank, ref_ptr & parentOverlay) const; void DeleteHandle(ref_ptr const & handle); + ref_ptr FindParent(ref_ptr handle, int searchingRank) const; + void DeleteHandleWithParents(ref_ptr handle, int currentRank); + int m_frameCounter; array>, dp::OverlayRanksCount> m_handles; unordered_set, detail::OverlayHasher> m_handlesCache; diff --git a/drape/shaders/colored_symbol_billboard_shader.vsh b/drape/shaders/colored_symbol_billboard_shader.vsh new file mode 100644 index 0000000000..5bc383482a --- /dev/null +++ b/drape/shaders/colored_symbol_billboard_shader.vsh @@ -0,0 +1,35 @@ +attribute vec3 a_position; +attribute vec4 a_normal; +attribute vec4 a_colorTexCoords; + +uniform mat4 modelView; +uniform mat4 projection; +uniform mat4 pivotTransform; + +varying vec4 v_normal; +#ifdef ENABLE_VTF +uniform sampler2D u_colorTex; +varying lowp vec4 v_color; +#else +varying vec2 v_colorTexCoords; +#endif + +void main(void) +{ + vec4 pivot = vec4(a_position.xyz, 1.0) * modelView; + vec4 offset = vec4(a_normal.xy + a_colorTexCoords.zw, 0.0, 0.0) * projection; + + vec4 projectedPivot = pivot * projection; + float logicZ = projectedPivot.z / projectedPivot.w; + vec4 transformedPivot = pivotTransform * vec4(projectedPivot.xy, 0.0, projectedPivot.w); + + vec4 scale = pivotTransform * vec4(1.0, -1.0, 0.0, 1.0); + gl_Position = vec4(transformedPivot.xy / transformedPivot.w, logicZ, 1.0) + vec4(offset.xy / scale.w * scale.x, 0.0, 0.0); + +#ifdef ENABLE_VTF + v_color = texture2D(u_colorTex, a_colorTexCoords.xy); +#else + v_colorTexCoords = a_colorTexCoords.xy; +#endif + v_normal = a_normal; +} diff --git a/drape/shaders/colored_symbol_shader.fsh b/drape/shaders/colored_symbol_shader.fsh new file mode 100644 index 0000000000..376484fa33 --- /dev/null +++ b/drape/shaders/colored_symbol_shader.fsh @@ -0,0 +1,32 @@ +uniform float u_opacity; + +varying vec4 v_normal; +#ifdef ENABLE_VTF +varying lowp vec4 v_color; +#else +uniform sampler2D u_colorTex; +varying vec2 v_colorTexCoords; +#endif + +const float aaPixelsCount = 2.5; + +void main(void) +{ +#ifdef ENABLE_VTF + lowp vec4 color = v_color; +#else + lowp vec4 color = texture2D(u_colorTex, v_colorTexCoords); +#endif + + float r1 = (v_normal.z - aaPixelsCount) * (v_normal.z - aaPixelsCount); + float r2 = v_normal.x * v_normal.x + v_normal.y * v_normal.y; + float r3 = v_normal.z * v_normal.z; + float alpha = mix(step(r3, r2), smoothstep(r1, r3, r2), v_normal.w); + + lowp vec4 finalColor = color; + finalColor.a = finalColor.a * u_opacity * (1.0 - alpha); + if (finalColor.a == 0.0) + discard; + + gl_FragColor = finalColor; +} diff --git a/drape/shaders/colored_symbol_shader.vsh b/drape/shaders/colored_symbol_shader.vsh new file mode 100644 index 0000000000..b3035827a5 --- /dev/null +++ b/drape/shaders/colored_symbol_shader.vsh @@ -0,0 +1,34 @@ +attribute vec3 a_position; +attribute vec4 a_normal; +attribute vec4 a_colorTexCoords; + +uniform mat4 modelView; +uniform mat4 projection; +uniform mat4 pivotTransform; + +varying vec4 v_normal; +#ifdef ENABLE_VTF +uniform sampler2D u_colorTex; +varying lowp vec4 v_color; +#else +varying vec2 v_colorTexCoords; +#endif + +void main(void) +{ + vec4 p = vec4(a_position, 1) * modelView; + vec4 pos = vec4(a_normal.xy + a_colorTexCoords.zw, 0, 0) + p; + pos = pos * projection; + + float w = pos.w; + pos.xyw = (pivotTransform * vec4(pos.xy, 0.0, w)).xyw; + pos.z *= pos.w / w; + gl_Position = pos; + +#ifdef ENABLE_VTF + v_color = texture2D(u_colorTex, a_colorTexCoords.xy); +#else + v_colorTexCoords = a_colorTexCoords.xy; +#endif + v_normal = a_normal; +} diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index c2033f7e0b..7536a0660d 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -1,3 +1,6 @@ +TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh +MASKED_TEXTURING_PROGRAM masked_texturing_vertex_shader.vsh masked_texturing_fragment_shader.fsh +COLORED_SYMBOL_PROGRAM colored_symbol_shader.vsh colored_symbol_shader.fsh TEXT_OUTLINED_PROGRAM text_outlined_vertex_shader.vsh text_fragment_shader.fsh TEXT_PROGRAM text_vertex_shader.vsh text_fragment_shader.fsh TEXT_FIXED_PROGRAM text_vertex_shader.vsh text_fixed_fragment_shader.fsh @@ -6,8 +9,6 @@ AREA_PROGRAM area_vertex_shader.vsh solid_color_fragment_shader.fsh AREA_OUTLINE_PROGRAM area_vertex_shader.vsh solid_color_fragment_shader.fsh AREA_3D_PROGRAM area3d_vertex_shader.vsh texturing3d_fragment_shader.fsh AREA_3D_OUTLINE_PROGRAM area3d_outline_vertex_shader.vsh solid_color_fragment_shader.fsh -TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh -MASKED_TEXTURING_PROGRAM masked_texturing_vertex_shader.vsh masked_texturing_fragment_shader.fsh LINE_PROGRAM line_vertex_shader.vsh line_fragment_shader.fsh CAP_JOIN_PROGRAM circle_shader.vsh circle_shader.fsh DASHED_LINE_PROGRAM dashed_vertex_shader.vsh dashed_fragment_shader.fsh @@ -26,6 +27,7 @@ TRANSPARENT_LAYER_PROGRAM transparent_layer_vertex_shader.vsh transparent_layer_ ARROW_3D_PROGRAM arrow3d_vertex_shader.vsh arrow3d_fragment_shader.fsh ARROW_3D_SHADOW_PROGRAM arrow3d_shadow_vertex_shader.vsh arrow3d_shadow_fragment_shader.fsh ARROW_3D_OUTLINE_PROGRAM arrow3d_shadow_vertex_shader.vsh arrow3d_outline_fragment_shader.fsh +COLORED_SYMBOL_BILLBOARD_PROGRAM colored_symbol_billboard_shader.vsh colored_symbol_shader.fsh TEXTURING_BILLBOARD_PROGRAM texturing_billboard_vertex_shader.vsh texturing_fragment_shader.fsh MASKED_TEXTURING_BILLBOARD_PROGRAM masked_texturing_billboard_vertex_shader.vsh masked_texturing_fragment_shader.fsh TEXT_OUTLINED_BILLBOARD_PROGRAM text_outlined_billboard_vertex_shader.vsh text_fragment_shader.fsh diff --git a/drape/symbols_texture.cpp b/drape/symbols_texture.cpp index 5db348a0da..bc8dfd381d 100644 --- a/drape/symbols_texture.cpp +++ b/drape/symbols_texture.cpp @@ -162,7 +162,7 @@ void LoadSymbols(string const & skinPathName, bool convertToUV, ASSERT(glm::isPowerOfTwo(w), (w)); ASSERT(glm::isPowerOfTwo(h), (h)); - if (width == w && height == h) + if (width == static_cast(w) && height == static_cast(h)) { completionHandler(data, width, height); } diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp index 9a4b0c7e9c..531e1215fc 100644 --- a/drape/texture_manager.cpp +++ b/drape/texture_manager.cpp @@ -143,17 +143,17 @@ void TextureManager::BaseRegion::SetTexture(ref_ptr texture) m_texture = texture; } -m2::PointU TextureManager::BaseRegion::GetPixelSize() const +m2::PointF TextureManager::BaseRegion::GetPixelSize() const { ASSERT(IsValid(), ()); m2::RectF const & texRect = m_info->GetTexRect(); - return m2::PointU(ceil(texRect.SizeX() * m_texture->GetWidth()), - ceil(texRect.SizeY() * m_texture->GetHeight())); + return m2::PointF(texRect.SizeX() * m_texture->GetWidth(), + texRect.SizeY() * m_texture->GetHeight()); } -uint32_t TextureManager::BaseRegion::GetPixelHeight() const +float TextureManager::BaseRegion::GetPixelHeight() const { - return ceil(m_info->GetTexRect().SizeY() * m_texture->GetHeight()); + return m_info->GetTexRect().SizeY() * m_texture->GetHeight(); } m2::RectF const & TextureManager::BaseRegion::GetTexRect() const diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp index ce7779511c..60d18f18a7 100644 --- a/drape/texture_manager.hpp +++ b/drape/texture_manager.hpp @@ -28,8 +28,8 @@ public: ref_ptr GetTexture() const { return m_texture; } bool IsValid() const; - m2::PointU GetPixelSize() const; - uint32_t GetPixelHeight() const; + m2::PointF GetPixelSize() const; + float GetPixelHeight() const; m2::RectF const & GetTexRect() const; protected: diff --git a/drape/utils/vertex_decl.cpp b/drape/utils/vertex_decl.cpp index a80a9a9149..8aa7670d6c 100644 --- a/drape/utils/vertex_decl.cpp +++ b/drape/utils/vertex_decl.cpp @@ -18,6 +18,7 @@ enum VertexType Line, DashedLine, Route, + ColoredSymbol, TypeCount }; @@ -165,6 +166,20 @@ dp::BindingInfo RouteBindingInit() return filler.m_info; } +dp::BindingInfo ColoredSymbolBindingInit() +{ + static_assert(sizeof(ColoredSymbolVertex) == sizeof(ColoredSymbolVertex::TPosition) + + sizeof(ColoredSymbolVertex::TNormal) + + sizeof(ColoredSymbolVertex::TTexCoord), ""); + + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_colorTexCoords"); + + return filler.m_info; +} + BindingNode g_bindingNodes[TypeCount]; TInitFunction g_initFunctions[TypeCount] = { @@ -177,7 +192,8 @@ TInitFunction g_initFunctions[TypeCount] = &TextDynamicBindingInit, &LineBindingInit, &DashedLineBindingInit, - &RouteBindingInit + &RouteBindingInit, + &ColoredSymbolBindingInit }; dp::BindingInfo const & GetBinding(VertexType type) @@ -391,5 +407,25 @@ dp::BindingInfo const & TextStaticVertex::GetBindingInfo() return GetBinding(TextStatic); } +ColoredSymbolVertex::ColoredSymbolVertex() + : m_position(0.0, 0.0, 0.0) + , m_normal(0.0, 0.0, 0.0, 0.0) + , m_colorTexCoord(0.0, 0.0, 0.0, 0.0) +{ +} + +ColoredSymbolVertex::ColoredSymbolVertex(TPosition const & position, TNormal const & normal, + TTexCoord const & colorTexCoord) + : m_position(position) + , m_normal(normal) + , m_colorTexCoord(colorTexCoord) +{ +} + +dp::BindingInfo const & ColoredSymbolVertex::GetBindingInfo() +{ + return GetBinding(ColoredSymbol); +} + } //namespace gpu diff --git a/drape/utils/vertex_decl.hpp b/drape/utils/vertex_decl.hpp index b0ff4955ba..85f95a1e03 100644 --- a/drape/utils/vertex_decl.hpp +++ b/drape/utils/vertex_decl.hpp @@ -158,4 +158,20 @@ struct RouteVertex : BaseVertex static dp::BindingInfo const & GetBindingInfo(); }; +struct ColoredSymbolVertex : BaseVertex +{ + using TNormal = glsl::vec4; + using TTexCoord = glsl::vec4; + + ColoredSymbolVertex(); + ColoredSymbolVertex(TPosition const & position, TNormal const & normal, + TTexCoord const & colorTexCoord); + + TPosition m_position; + TNormal m_normal; + TTexCoord m_colorTexCoord; + + static dp::BindingInfo const & GetBindingInfo(); +}; + } // namespace gpu diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index 8cae36a799..af376b9d8f 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -57,10 +57,10 @@ set( batch_merge_helper.cpp batch_merge_helper.hpp batchers_pool.hpp - circle_shape.cpp - circle_shape.hpp color_constants.cpp color_constants.hpp + colored_symbol_shape.cpp + colored_symbol_shape.hpp drape_api.cpp drape_api.hpp drape_api_builder.cpp diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 19ca1d5cb3..dbb7306721 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -2,11 +2,12 @@ #include "drape_frontend/visual_params.hpp" #include "drape_frontend/area_shape.hpp" +#include "drape_frontend/color_constants.hpp" #include "drape_frontend/line_shape.hpp" #include "drape_frontend/text_shape.hpp" #include "drape_frontend/poi_symbol_shape.hpp" #include "drape_frontend/path_symbol_shape.hpp" -#include "drape_frontend/circle_shape.hpp" +#include "drape_frontend/colored_symbol_shape.hpp" #include "drape_frontend/path_text_shape.hpp" #include "indexer/drawing_rules.hpp" @@ -22,17 +23,17 @@ #include "base/logging.hpp" -#include "std/algorithm.hpp" -#include "std/mutex.hpp" -#include "std/sstream.hpp" -#include "std/utility.hpp" +#include +#include +#include +#include +#include namespace df { namespace { - double const kMinVisibleFontSize = 8.0; string const kStarSymbol = "★"; @@ -41,6 +42,10 @@ string const kPriceSymbol = "$"; int const kLineSimplifyLevelStart = 10; int const kLineSimplifyLevelEnd = 12; +double const kPathTextBaseTextIndex = 0; +double const kPathTextBaseTextStep = 100; +double const kShieldBaseTextIndex = 1000; + dp::Color ToDrapeColor(uint32_t src) { return dp::Extract(src, 255 - (src >> 24)); @@ -152,7 +157,7 @@ void Extract(::LineDefProto const * lineRule, df::LineViewParams & params) } } -void CaptionDefProtoToFontDecl(CaptionDefProto const * capRule, dp::FontDecl ¶ms) +void CaptionDefProtoToFontDecl(CaptionDefProto const * capRule, dp::FontDecl & params) { double const vs = df::VisualParams::Instance().GetVisualScale(); params.m_color = ToDrapeColor(capRule->color()); @@ -164,13 +169,16 @@ void CaptionDefProtoToFontDecl(CaptionDefProto const * capRule, dp::FontDecl &pa params.m_isSdf = false; } -void ShieldRuleProtoToFontDecl(ShieldRuleProto const * shieldRule, dp::FontDecl ¶ms) +void ShieldRuleProtoToFontDecl(ShieldRuleProto const * shieldRule, dp::FontDecl & params) { - params.m_color = ToDrapeColor(shieldRule->color()); - params.m_size = max(kMinVisibleFontSize, shieldRule->height() * df::VisualParams::Instance().GetVisualScale()); + double const vs = df::VisualParams::Instance().GetVisualScale(); + params.m_color = ToDrapeColor(shieldRule->text_color()); + params.m_size = max(kMinVisibleFontSize, shieldRule->height() * vs); + if (shieldRule->has_text_stroke_color()) + params.m_outlineColor = ToDrapeColor(shieldRule->text_stroke_color()); - if (shieldRule->has_stroke_color()) - params.m_outlineColor = ToDrapeColor(shieldRule->stroke_color()); + if (vs < df::VisualParams::kHdpiScale) + params.m_isSdf = false; } dp::Anchor GetAnchor(CaptionDefProto const * capRule) @@ -224,17 +232,95 @@ uint16_t CalculateHotelOverlayPriority(BaseApplyFeature::HotelData const & data) return 0; } -} // namespace +bool IsSymbolRoadShield(ftypes::RoadShield const & shield) +{ + return shield.m_type == ftypes::RoadShieldType::US_Interstate || + shield.m_type == ftypes::RoadShieldType::US_Highway; +} -BaseApplyFeature::BaseApplyFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, +std::string GetRoadShieldSymbolName(ftypes::RoadShield const & shield, double fontScale) +{ + std::string result = ""; + if (shield.m_type == ftypes::RoadShieldType::US_Interstate) + result = shield.m_name.size() <= 2 ? "shield-us-i-thin" : "shield-us-i-wide"; + else if (shield.m_type == ftypes::RoadShieldType::US_Highway) + result = shield.m_name.size() <= 2 ? "shield-us-hw-thin" : "shield-us-hw-wide"; + + if (!result.empty() && fontScale > 1.0) + result += "-scaled"; + + return result; +} + +bool IsColoredRoadShield(ftypes::RoadShield const & shield) +{ + return shield.m_type == ftypes::RoadShieldType::Default || + shield.m_type == ftypes::RoadShieldType::UK_Highway || + shield.m_type == ftypes::RoadShieldType::UK_Motorway || + shield.m_type == ftypes::RoadShieldType::Russia_Highway || + shield.m_type == ftypes::RoadShieldType::Russia_Motorway; +} + +dp::FontDecl GetRoadShieldTextFont(MapStyle const & style, dp::FontDecl const & baseFont, + ftypes::RoadShield const & shield) +{ + dp::FontDecl f = baseFont; + f.m_outlineColor = dp::Color::Transparent(); + + static std::unordered_map kColors = { + {static_cast(ftypes::RoadShieldType::UK_Motorway), df::RoadShieldBlueText}, + {static_cast(ftypes::RoadShieldType::UK_Highway), df::RoadShieldUKGreenText}, + {static_cast(ftypes::RoadShieldType::US_Interstate), df::RoadShieldUSInterstateText}, + {static_cast(ftypes::RoadShieldType::US_Highway), df::RoadShieldUSHighwayText}, + {static_cast(ftypes::RoadShieldType::Russia_Highway), df::RoadShieldBlueText}, + {static_cast(ftypes::RoadShieldType::Russia_Motorway), df::RoadShieldGreenText}, + }; + + auto it = kColors.find(static_cast(shield.m_type)); + if (it != kColors.end()) + f.m_color = df::GetColorConstant(style, it->second); + + return f; +} + +dp::Color GetRoadShieldColor(MapStyle const & style, dp::Color const & baseColor, + ftypes::RoadShield const & shield) +{ + static std::unordered_map kColors = { + {static_cast(ftypes::RoadShieldType::UK_Motorway), df::RoadShieldBlueBackground}, + {static_cast(ftypes::RoadShieldType::UK_Highway), df::RoadShieldGreenBackground}, + {static_cast(ftypes::RoadShieldType::Russia_Highway), df::RoadShieldBlueBackground}, + {static_cast(ftypes::RoadShieldType::Russia_Motorway), df::RoadShieldGreenBackground}, + }; + + auto it = kColors.find(static_cast(shield.m_type)); + if (it != kColors.end()) + return df::GetColorConstant(style, it->second); + + return baseColor; +} + +float GetRoadShieldOutlineWidth(float baseWidth, ftypes::RoadShield const & shield) +{ + if (shield.m_type == ftypes::RoadShieldType::UK_Highway || + shield.m_type == ftypes::RoadShieldType::UK_Motorway || + shield.m_type == ftypes::RoadShieldType::Russia_Highway || + shield.m_type == ftypes::RoadShieldType::Russia_Motorway) + return 0.0f; + + return baseWidth; +} +} // namespace + +BaseApplyFeature::BaseApplyFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, int minVisibleScale, uint8_t rank, CaptionDescription const & captions) : m_insertShape(insertShape) , m_id(id) , m_captions(captions) , m_minVisibleScale(minVisibleScale) , m_rank(rank) - , m_tileCenter(tileCenter) + , m_tileKey(tileKey) + , m_tileRect(tileKey.GetGlobalRect()) { ASSERT(m_insertShape != nullptr, ()); } @@ -289,20 +375,17 @@ void BaseApplyFeature::SetHotelData(HotelData && hotelData) m_hotelData = move(hotelData); } -ApplyPointFeature::ApplyPointFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, +ApplyPointFeature::ApplyPointFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, int minVisibleScale, uint8_t rank, CaptionDescription const & captions, float posZ) - : TBase(tileCenter, insertShape, id, minVisibleScale, rank, captions) + : TBase(tileKey, insertShape, id, minVisibleScale, rank, captions) , m_posZ(posZ) , m_hasPoint(false) , m_hasArea(false) , m_createdByEditor(false) , m_obsoleteInEditor(false) , m_symbolDepth(dp::minDepth) - , m_circleDepth(dp::minDepth) , m_symbolRule(nullptr) - , m_circleRule(nullptr) { } @@ -332,20 +415,13 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule) m_symbolRule = symRule; } - CircleRuleProto const * circleRule = pRule->GetCircle(); - if (circleRule != nullptr) - { - m_circleDepth = depth; - m_circleRule = circleRule; - } - - bool const hasPOI = (m_symbolRule != nullptr || m_circleRule != nullptr); + bool const hasPOI = m_symbolRule != nullptr; bool const isNode = (pRule->GetType() & drule::node) != 0; CaptionDefProto const * capRule = pRule->GetCaption(0); if (capRule && isNode) { TextViewParams params; - params.m_tileCenter = m_tileCenter; + params.m_tileCenter = m_tileRect.Center(); ExtractCaptionParams(capRule, pRule->GetCaption(1), depth, params); params.m_minVisibleScale = m_minVisibleScale; params.m_rank = m_rank; @@ -359,7 +435,7 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule) // for kHotelMode and this shape will not be displayed in this case. if (m_hotelData.m_isHotel) displacementMode = dp::displacement::kDefaultMode; - m_insertShape(make_unique_dp(m_centerPoint, params, + m_insertShape(make_unique_dp(m_centerPoint, params, m_tileKey, hasPOI, 0 /* textIndex */, true /* affectedByZoomPriority */, displacementMode)); @@ -375,7 +451,8 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule) params.m_secondaryText = ExtractHotelInfo(); params.m_secondaryOptional = false; uint16_t const priority = CalculateHotelOverlayPriority(m_hotelData); - m_insertShape(make_unique_dp(m_centerPoint, params, hasPOI, 0 /* textIndex */, + m_insertShape(make_unique_dp(m_centerPoint, params, m_tileKey, + hasPOI, 0 /* textIndex */, true /* affectedByZoomPriority */, dp::displacement::kHotelMode, priority)); } @@ -384,59 +461,39 @@ void ApplyPointFeature::ProcessRule(Stylist::TRuleWrapper const & rule) void ApplyPointFeature::Finish() { - if (m_circleRule && m_symbolRule) - { - // draw circledSymbol - } - else if (m_circleRule) - { - CircleViewParams params(m_id); - params.m_tileCenter = m_tileCenter; - params.m_depth = m_circleDepth; - params.m_minVisibleScale = m_minVisibleScale; - params.m_rank = m_rank; - params.m_color = ToDrapeColor(m_circleRule->color()); - params.m_radius = m_circleRule->radius(); - params.m_hasArea = m_hasArea; - params.m_createdByEditor = m_createdByEditor; - m_insertShape(make_unique_dp(m_centerPoint, params, true /* need overlay */)); - } - else if (m_symbolRule) - { - PoiSymbolViewParams params(m_id); - params.m_tileCenter = m_tileCenter; - params.m_depth = m_symbolDepth; - params.m_minVisibleScale = m_minVisibleScale; - params.m_rank = m_rank; - params.m_symbolName = m_symbolRule->name(); - float const mainScale = df::VisualParams::Instance().GetVisualScale(); - params.m_extendingSize = m_symbolRule->has_min_distance() ? mainScale * m_symbolRule->min_distance() : 0; - params.m_posZ = m_posZ; - params.m_hasArea = m_hasArea; - params.m_createdByEditor = m_createdByEditor; - params.m_obsoleteInEditor = m_obsoleteInEditor; + if (m_symbolRule == nullptr) + return; - m_insertShape(make_unique_dp(m_centerPoint, params, - m_hotelData.m_isHotel ? dp::displacement::kDefaultMode : - dp::displacement::kAllModes)); - if (m_hotelData.m_isHotel) - { - uint16_t const priority = CalculateHotelOverlayPriority(m_hotelData); - m_insertShape(make_unique_dp(m_centerPoint, params, - dp::displacement::kHotelMode, priority)); - } + PoiSymbolViewParams params(m_id); + params.m_tileCenter = m_tileRect.Center(); + params.m_depth = m_symbolDepth; + params.m_minVisibleScale = m_minVisibleScale; + params.m_rank = m_rank; + params.m_symbolName = m_symbolRule->name(); + float const mainScale = df::VisualParams::Instance().GetVisualScale(); + params.m_extendingSize = m_symbolRule->has_min_distance() ? mainScale * m_symbolRule->min_distance() : 0; + params.m_posZ = m_posZ; + params.m_hasArea = m_hasArea; + params.m_createdByEditor = m_createdByEditor; + params.m_obsoleteInEditor = m_obsoleteInEditor; + + m_insertShape(make_unique_dp(m_centerPoint, params, m_tileKey, 0 /* text index */, + m_hotelData.m_isHotel ? dp::displacement::kDefaultMode : + dp::displacement::kAllModes)); + if (m_hotelData.m_isHotel) + { + uint16_t const priority = CalculateHotelOverlayPriority(m_hotelData); + m_insertShape(make_unique_dp(m_centerPoint, params, m_tileKey, 0 /* text index */, + dp::displacement::kHotelMode, priority)); } } -ApplyAreaFeature::ApplyAreaFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, bool isBuilding, float minPosZ, - float posZ, int minVisibleScale, uint8_t rank, bool generateOutline, - CaptionDescription const & captions) - : TBase(tileCenter, insertShape, id, minVisibleScale, rank, captions, posZ) +ApplyAreaFeature::ApplyAreaFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, + bool isBuilding, float minPosZ, float posZ, int minVisibleScale, + uint8_t rank, bool generateOutline, CaptionDescription const & captions) + : TBase(tileKey, insertShape, id, minVisibleScale, rank, captions, posZ) , m_minPosZ(minPosZ) , m_isBuilding(isBuilding) - , m_clipRect(clipRect) , m_generateOutline(generateOutline) {} @@ -466,9 +523,9 @@ void ApplyAreaFeature::operator()(m2::PointD const & p1, m2::PointD const & p2, }; if (m2::CrossProduct(p2 - p1, p3 - p1) < 0) - m2::ClipTriangleByRect(m_clipRect, p1, p2, p3, clipFunctor); + m2::ClipTriangleByRect(m_tileRect, p1, p2, p3, clipFunctor); else - m2::ClipTriangleByRect(m_clipRect, p1, p3, p2, clipFunctor); + m2::ClipTriangleByRect(m_tileRect, p1, p3, p2, clipFunctor); } void ApplyAreaFeature::ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD const & p2, @@ -595,7 +652,7 @@ void ApplyAreaFeature::ProcessRule(Stylist::TRuleWrapper const & rule) if (areaRule && !m_triangles.empty()) { AreaViewParams params; - params.m_tileCenter = m_tileCenter; + params.m_tileCenter = m_tileRect.Center(); params.m_depth = depth; params.m_color = ToDrapeColor(areaRule->color()); params.m_minVisibleScale = m_minVisibleScale; @@ -620,19 +677,16 @@ void ApplyAreaFeature::ProcessRule(Stylist::TRuleWrapper const & rule) } } -ApplyLineFeature::ApplyLineFeature(m2::PointD const & tileCenter, double currentScaleGtoP, - TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, int minVisibleScale, uint8_t rank, - CaptionDescription const & captions, int zoomLevel, size_t pointsCount) - : TBase(tileCenter, insertShape, id, minVisibleScale, rank, captions) +ApplyLineFeature::ApplyLineFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, + double currentScaleGtoP, int minVisibleScale, uint8_t rank, + CaptionDescription const & captions, size_t pointsCount) + : TBase(tileKey, insertShape, id, minVisibleScale, rank, captions) , m_currentScaleGtoP(currentScaleGtoP) , m_sqrScale(math::sqr(m_currentScaleGtoP)) - , m_simplify(zoomLevel >= kLineSimplifyLevelStart && zoomLevel <= kLineSimplifyLevelEnd) - , m_zoomLevel(zoomLevel) + , m_simplify(tileKey.m_zoomLevel >= kLineSimplifyLevelStart && tileKey.m_zoomLevel <= kLineSimplifyLevelEnd) , m_initialPointsCount(pointsCount) , m_shieldDepth(0.0) , m_shieldRule(nullptr) - , m_clipRect(move(clipRect)) #ifdef CALC_FILTERED_POINTS , m_readedCount(0) #endif @@ -686,7 +740,7 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) LineDefProto const * pLineRule = pRule->GetLine(); ShieldRuleProto const * pShieldRule = pRule->GetShield(); - m_clippedSplines = m2::ClipSplineByRect(m_clipRect, m_spline); + m_clippedSplines = m2::ClipSplineByRect(m_tileRect, m_spline); if (m_clippedSplines.empty()) return; @@ -698,7 +752,7 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) CaptionDefProtoToFontDecl(pCaptionRule, fontDecl); PathTextViewParams params; - params.m_tileCenter = m_tileCenter; + params.m_tileCenter = m_tileRect.Center(); params.m_featureID = m_id; params.m_depth = depth; params.m_minVisibleScale = m_minVisibleScale; @@ -707,8 +761,12 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) params.m_textFont = fontDecl; params.m_baseGtoPScale = m_currentScaleGtoP; + uint32_t baseTextIndex = kPathTextBaseTextIndex; for (auto const & spline : m_clippedSplines) - m_insertShape(make_unique_dp(spline, params)); + { + m_insertShape(make_unique_dp(spline, params, m_tileKey, baseTextIndex)); + baseTextIndex += kPathTextBaseTextStep; + } } if (pLineRule != nullptr) @@ -717,7 +775,7 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) { PathSymProto const & symRule = pLineRule->pathsym(); PathSymbolViewParams params; - params.m_tileCenter = m_tileCenter; + params.m_tileCenter = m_tileRect.Center(); params.m_depth = depth; params.m_minVisibleScale = m_minVisibleScale; params.m_rank = m_rank; @@ -733,13 +791,13 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) else { LineViewParams params; - params.m_tileCenter = m_tileCenter; + params.m_tileCenter = m_tileRect.Center(); Extract(pLineRule, params); params.m_depth = depth; params.m_minVisibleScale = m_minVisibleScale; params.m_rank = m_rank; params.m_baseGtoPScale = m_currentScaleGtoP; - params.m_zoomLevel = m_zoomLevel; + params.m_zoomLevel = m_tileKey.m_zoomLevel; for (auto const & spline : m_clippedSplines) m_insertShape(make_unique_dp(spline, params)); @@ -753,7 +811,91 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) } } -void ApplyLineFeature::Finish() +void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shield, TextViewParams & textParams, + ColoredSymbolViewParams & symbolParams, + PoiSymbolViewParams & poiParams) +{ + ASSERT (m_shieldRule != nullptr, ()); + + string const & roadNumber = shield.m_name; + float const mainScale = df::VisualParams::Instance().GetVisualScale(); + auto const style = GetStyleReader().GetCurrentStyle(); + double const fontScale = df::VisualParams::Instance().GetFontScale(); + + // Text properties. + dp::FontDecl baseFont; + ShieldRuleProtoToFontDecl(m_shieldRule, baseFont); + dp::FontDecl font = GetRoadShieldTextFont(style, baseFont, shield); + textParams.m_tileCenter = m_tileRect.Center(); + textParams.m_depth = m_shieldDepth; + textParams.m_minVisibleScale = m_minVisibleScale; + textParams.m_rank = m_rank; + textParams.m_anchor = dp::Center; + textParams.m_featureID = m_id; + textParams.m_primaryText = roadNumber; + textParams.m_primaryTextFont = font; + textParams.m_primaryOffset = m2::PointF(0, 0); + textParams.m_primaryOptional = false; + textParams.m_secondaryOptional = false; + textParams.m_extendingSize = 0; + + // Calculate width and height of a shield. + float const shieldWidth = (font.m_size * 0.5 * roadNumber.size() + 10.0f * mainScale) * fontScale; + float const shieldHeight = (font.m_size + 3.0f * mainScale) * fontScale; + textParams.m_limitedText = true; + textParams.m_limits = m2::PointF(shieldWidth, shieldHeight) * 0.9f; + + if (IsColoredRoadShield(shield)) + { + // Generated symbol properties. + symbolParams.m_featureID = m_id; + symbolParams.m_tileCenter = m_tileRect.Center(); + symbolParams.m_depth = m_shieldDepth; + symbolParams.m_minVisibleScale = m_minVisibleScale; + symbolParams.m_rank = m_rank; + symbolParams.m_shape = ColoredSymbolViewParams::Shape::RoundedRectangle; + symbolParams.m_radiusInPixels = 2.5f * mainScale; + symbolParams.m_color = ToDrapeColor(m_shieldRule->color()); + if (m_shieldRule->has_stroke_color()) + { + symbolParams.m_outlineColor = ToDrapeColor(m_shieldRule->stroke_color()); + symbolParams.m_outlineWidth = 1.0f * mainScale; + } + symbolParams.m_sizeInPixels = m2::PointF(shieldWidth, shieldHeight); + symbolParams.m_outlineWidth = GetRoadShieldOutlineWidth(symbolParams.m_outlineWidth, shield); + symbolParams.m_color = GetRoadShieldColor(style, symbolParams.m_color, shield); + } + + // Image symbol properties. + if (IsSymbolRoadShield(shield)) + { + std::string symbolName = GetRoadShieldSymbolName(shield, fontScale); + if (!symbolName.empty() && !shield.m_additionalText.empty()) + { + textParams.m_anchor = dp::Top; + textParams.m_secondaryText = shield.m_additionalText; + textParams.m_secondaryTextFont = textParams.m_primaryTextFont; + textParams.m_secondaryTextFont.m_color = df::GetColorConstant(style, df::RoadShieldAddText); + textParams.m_secondaryTextFont.m_outlineColor = df::GetColorConstant(style, df::RoadShieldAddTextOutline); + textParams.m_primaryOffset = m2::PointF(0.0f, -0.5f * textParams.m_primaryTextFont.m_size); + textParams.m_secondaryTextFont.m_size *= 0.9f; + textParams.m_secondaryOffset = m2::PointF(0.0f, 3.0f * mainScale); + } + + poiParams.m_tileCenter = m_tileRect.Center(); + poiParams.m_depth = m_shieldDepth; + poiParams.m_minVisibleScale = m_minVisibleScale; + poiParams.m_rank = m_rank; + poiParams.m_symbolName = symbolName; + poiParams.m_extendingSize = 0; + poiParams.m_posZ = 0.0f; + poiParams.m_hasArea = false; + poiParams.m_createdByEditor = false; + poiParams.m_obsoleteInEditor = false; + } +} + +void ApplyLineFeature::Finish(std::vector && roadShields) { #ifdef CALC_FILTERED_POINTS LinesStat::Get().InsertLine(m_id, m_currentScaleGtoP, m_readedCount, m_spline->GetSize()); @@ -762,52 +904,53 @@ void ApplyLineFeature::Finish() if (m_shieldRule == nullptr || m_clippedSplines.empty()) return; - string const & roadNumber = m_captions.GetRoadNumber(); - if (roadNumber.empty()) - return; - - dp::FontDecl font; - ShieldRuleProtoToFontDecl(m_shieldRule, font); - + uint32_t constexpr kDefaultMinDistance = 50; float const mainScale = df::VisualParams::Instance().GetVisualScale(); - TextViewParams viewParams; - viewParams.m_tileCenter = m_tileCenter; - viewParams.m_depth = m_shieldDepth; - viewParams.m_minVisibleScale = m_minVisibleScale; - viewParams.m_rank = m_rank; - viewParams.m_anchor = dp::Center; - viewParams.m_featureID = m_id; - viewParams.m_primaryText = roadNumber; - viewParams.m_primaryTextFont = font; - viewParams.m_primaryOffset = m2::PointF(0, 0); - viewParams.m_primaryOptional = true; - viewParams.m_secondaryOptional = true; - viewParams.m_extendingSize = m_shieldRule->has_min_distance() ? mainScale * m_shieldRule->min_distance() : 0; - - for (auto const & spline : m_clippedSplines) + m2::PointD shieldOffset; + for (size_t shieldIndex = 0; shieldIndex < roadShields.size(); shieldIndex++) { - double const pathPixelLength = spline->GetLength() * m_currentScaleGtoP; - int const textHeight = static_cast(font.m_size); + ftypes::RoadShield const & shield = roadShields[shieldIndex]; + TextViewParams textParams; + ColoredSymbolViewParams symbolParams; + PoiSymbolViewParams poiParams(m_id); + GetRoadShieldsViewParams(shield, textParams, symbolParams, poiParams); - // I don't know why we draw by this, but it's work before and will work now - if (pathPixelLength > (roadNumber.size() + 2) * textHeight) + uint32_t minDistanceInPixels = mainScale * (m_shieldRule->has_min_distance() ? + m_shieldRule->min_distance() : kDefaultMinDistance); + if (minDistanceInPixels == 0) + minDistanceInPixels = mainScale * kDefaultMinDistance; + + uint32_t textIndex = kShieldBaseTextIndex * (shieldIndex + 1); + for (auto const & spline : m_clippedSplines) { - // TODO in future we need to choose emptySpace according GtoP scale. - double const emptySpace = 1000.0; - int const count = static_cast((pathPixelLength / emptySpace) + 2); - double const splineStep = pathPixelLength / count; - + double const pathPixelLength = spline->GetLength() * m_currentScaleGtoP; + uint32_t const shieldsCount = static_cast(pathPixelLength / minDistanceInPixels); + if (shieldsCount == 0) + continue; + double const splineStep = spline->GetLength() / (shieldsCount + 1); m2::Spline::iterator it = spline.CreateIterator(); - size_t textIndex = 0; - while (!it.BeginAgain()) + it.Advance(splineStep); + + for (uint32_t i = 0; i < shieldsCount && !it.BeginAgain(); i++) { - m_insertShape(make_unique_dp(it.m_pos, viewParams, false /* hasPOI */, - textIndex, false /* affectedByZoomPriority */)); + m_insertShape(make_unique_dp(shieldOffset + it.m_pos, textParams, m_tileKey, + true /* hasPOI */, textIndex, + false /* affectedByZoomPriority */)); + if (IsColoredRoadShield(shield)) + { + m_insertShape(make_unique_dp(shieldOffset + it.m_pos, symbolParams, m_tileKey, textIndex)); + } + else if (IsSymbolRoadShield(shield)) + { + m_insertShape(make_unique_dp(shieldOffset + it.m_pos, poiParams, m_tileKey, textIndex)); + } it.Advance(splineStep); textIndex++; } } + + shieldOffset += m2::PointD(symbolParams.m_sizeInPixels.x / m_currentScaleGtoP, 0.0); } } diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index e84d9f28a4..a03edfe314 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -6,6 +6,7 @@ #include "drape/pointers.hpp" +#include "indexer/ftypes_matcher.hpp" #include "indexer/point_to_int64.hpp" #include "geometry/point2d.hpp" @@ -15,7 +16,6 @@ #include "std/unordered_map.hpp" class CaptionDefProto; -class CircleRuleProto; class ShieldRuleProto; class SymbolRuleProto; @@ -33,8 +33,7 @@ using TInsertShapeFn = function && shape)>; class BaseApplyFeature { public: - BaseApplyFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, + BaseApplyFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, int minVisibleScale, uint8_t rank, CaptionDescription const & captions); virtual ~BaseApplyFeature() {} @@ -62,7 +61,8 @@ protected: uint8_t m_rank; HotelData m_hotelData; - m2::PointD m_tileCenter; + TileKey const m_tileKey; + m2::RectD const m_tileRect; }; class ApplyPointFeature : public BaseApplyFeature @@ -70,8 +70,7 @@ class ApplyPointFeature : public BaseApplyFeature using TBase = BaseApplyFeature; public: - ApplyPointFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, + ApplyPointFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, int minVisibleScale, uint8_t rank, CaptionDescription const & captions, float posZ); @@ -88,9 +87,7 @@ private: bool m_createdByEditor; bool m_obsoleteInEditor; double m_symbolDepth; - double m_circleDepth; SymbolRuleProto const * m_symbolRule; - CircleRuleProto const * m_circleRule; m2::PointF m_centerPoint; }; @@ -99,11 +96,9 @@ class ApplyAreaFeature : public ApplyPointFeature using TBase = ApplyPointFeature; public: - ApplyAreaFeature(m2::PointD const & tileCenter, - TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, bool isBuilding, float minPosZ, - float posZ, int minVisibleScale, uint8_t rank, bool generateOutline, - CaptionDescription const & captions); + ApplyAreaFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, + bool isBuilding, float minPosZ, float posZ, int minVisibleScale, + uint8_t rank, bool generateOutline, CaptionDescription const & captions); using TBase::operator (); @@ -125,10 +120,10 @@ private: buffer_vector m_points; buffer_vector, kBuildingOutlineSize> m_edges; + float const m_minPosZ; bool const m_isBuilding; - m2::RectD m_clipRect; - bool m_generateOutline; + bool const m_generateOutline; }; class ApplyLineFeature : public BaseApplyFeature @@ -136,30 +131,32 @@ class ApplyLineFeature : public BaseApplyFeature using TBase = BaseApplyFeature; public: - ApplyLineFeature(m2::PointD const & tileCenter, double currentScaleGtoP, - TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, int minVisibleScale, uint8_t rank, - CaptionDescription const & captions, int zoomLevel, size_t pointsCount); + ApplyLineFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, + double currentScaleGtoP, int minVisibleScale, uint8_t rank, + CaptionDescription const & captions, size_t pointsCount); void operator() (m2::PointD const & point); bool HasGeometry() const; void ProcessRule(Stylist::TRuleWrapper const & rule); - void Finish(); + void Finish(std::vector && roadShields); m2::PolylineD GetPolyline() const; private: + void GetRoadShieldsViewParams(ftypes::RoadShield const & shield, + TextViewParams & textParams, + ColoredSymbolViewParams & symbolParams, + PoiSymbolViewParams & poiParams); + m2::SharedSpline m_spline; vector m_clippedSplines; double m_currentScaleGtoP; double m_sqrScale; m2::PointD m_lastAddedPoint; bool m_simplify; - int m_zoomLevel; size_t m_initialPointsCount; double m_shieldDepth; ShieldRuleProto const * m_shieldRule; - m2::RectD m_clipRect; #ifdef CALC_FILTERED_POINTS int m_readedCount; diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index aafe232c2e..481bc14ebd 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -338,7 +338,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) ref_ptr msg = message; auto const & symbols = msg->GetSymbols(); - vector sizes(symbols.size()); + vector sizes(symbols.size()); for (size_t i = 0; i < symbols.size(); i++) { dp::TextureManager::SymbolRegion region; diff --git a/drape_frontend/circle_shape.cpp b/drape_frontend/circle_shape.cpp deleted file mode 100644 index cd4ec6a189..0000000000 --- a/drape_frontend/circle_shape.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "drape_frontend/circle_shape.hpp" - -#include "drape/utils/vertex_decl.hpp" -#include "drape/batcher.hpp" -#include "drape/attribute_provider.hpp" -#include "drape/glstate.hpp" -#include "drape/shader_def.hpp" -#include "drape/texture_manager.hpp" -#include "drape/overlay_handle.hpp" - -namespace df -{ - -CircleShape::CircleShape(m2::PointF const & mercatorPt, CircleViewParams const & params, bool needOverlay) - : m_pt(mercatorPt) - , m_params(params) - , m_needOverlay(needOverlay) -{} - -void CircleShape::Draw(ref_ptr batcher, ref_ptr textures) const -{ - int const TriangleCount = 20; - double const etalonSector = (2.0 * math::pi) / static_cast(TriangleCount); - - dp::TextureManager::ColorRegion region; - textures->GetColorRegion(m_params.m_color, region); - glsl::vec2 const colorPoint(glsl::ToVec2(region.GetTexRect().Center())); - glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(m_pt, m_params.m_tileCenter, kShapeCoordScalar)); - - buffer_vector vertexes; - vertexes.push_back(gpu::SolidTexturingVertex - { - glsl::vec4(pt, m_params.m_depth, 0.0f), - glsl::vec2(0.0f, 0.0f), - colorPoint - }); - - m2::PointD startNormal(0.0f, m_params.m_radius); - - for (size_t i = 0; i < TriangleCount + 1; ++i) - { - m2::PointD rotatedNormal = m2::Rotate(startNormal, (i) * etalonSector); - vertexes.push_back(gpu::SolidTexturingVertex - { - glsl::vec4(pt, m_params.m_depth, 0.0f), - glsl::ToVec2(rotatedNormal), - colorPoint - }); - } - - dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::OverlayLayer); - state.SetColorTexture(region.GetTexture()); - - dp::AttributeProvider provider(1, TriangleCount + 2); - provider.InitStream(0, gpu::SolidTexturingVertex::GetBindingInfo(), make_ref(vertexes.data())); - batcher->InsertTriangleFan(state, make_ref(&provider), CreateOverlay()); -} - -drape_ptr CircleShape::CreateOverlay() const -{ - if (!m_needOverlay) - return nullptr; - - double const handleSize = 2 * m_params.m_radius; - return make_unique_dp(m_params.m_id, dp::Center, m_pt, - m2::PointD(handleSize, handleSize), - GetOverlayPriority(), false /* isBound */, ""); -} - -uint64_t CircleShape::GetOverlayPriority() const -{ - // Set up maximum priority for shapes which created by user in the editor. - if (m_params.m_createdByEditor) - return dp::kPriorityMaskAll; - - // Set up minimal priority for shapes which belong to areas. - if (m_params.m_hasArea) - return 0; - - return dp::CalculateOverlayPriority(m_params.m_minVisibleScale, m_params.m_rank, m_params.m_depth); -} - -} // namespace df diff --git a/drape_frontend/circle_shape.hpp b/drape_frontend/circle_shape.hpp deleted file mode 100644 index f0e85b58a3..0000000000 --- a/drape_frontend/circle_shape.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "drape_frontend/map_shape.hpp" -#include "drape_frontend/shape_view_params.hpp" - -namespace dp -{ -class OverlayHandle; -} // namespace dp - -namespace df -{ - -class CircleShape : public MapShape -{ -public: - CircleShape(m2::PointF const & mercatorPt, CircleViewParams const & params, bool needOverlay); - - void Draw(ref_ptr batcher, ref_ptr textures) const override; - MapShapeType GetType() const override { return MapShapeType::OverlayType; } - -private: - uint64_t GetOverlayPriority() const; - drape_ptr CreateOverlay() const; - - m2::PointF m_pt; - CircleViewParams m_params; - bool m_needOverlay; -}; - -} //namespace df diff --git a/drape_frontend/color_constants.cpp b/drape_frontend/color_constants.cpp index 32f807168d..332332bf50 100644 --- a/drape_frontend/color_constants.cpp +++ b/drape_frontend/color_constants.cpp @@ -40,6 +40,15 @@ unordered_map> kColorConstants = { TrafficArrowLight, dp::Color(255, 255, 255, 255) }, { TrafficArrowDark, dp::Color(107, 81, 20, 255) }, { TrafficOutline, dp::Color(255, 255, 255, 255) }, + { RoadShieldAddText, dp::Color(0, 0, 0, 255) }, + { RoadShieldAddTextOutline, dp::Color(255, 255, 255, 255) }, + { RoadShieldUSInterstateText, dp::Color(255, 255, 255, 255) }, + { RoadShieldUSHighwayText, dp::Color(0, 0, 0, 255) }, + { RoadShieldBlueText, dp::Color(255, 255, 255, 255) }, + { RoadShieldGreenText, dp::Color(255, 255, 255, 255) }, + { RoadShieldUKGreenText, dp::Color(255, 204, 102, 255) }, + { RoadShieldBlueBackground, dp::Color(46, 111, 201, 255) }, + { RoadShieldGreenBackground, dp::Color(34, 114, 59, 255) }, } }, { MapStyleDark, @@ -72,6 +81,15 @@ unordered_map> kColorConstants = { TrafficArrowLight, dp::Color(170, 170, 170, 255) }, { TrafficArrowDark, dp::Color(30, 30, 30, 255) }, { TrafficOutline, dp::Color(0, 0, 0, 255) }, + { RoadShieldAddText, dp::Color(0, 0, 0, 255) }, + { RoadShieldAddTextOutline, dp::Color(255, 255, 255, 255) }, + { RoadShieldUSInterstateText, dp::Color(255, 255, 255, 255) }, + { RoadShieldUSHighwayText, dp::Color(0, 0, 0, 255) }, + { RoadShieldBlueText, dp::Color(255, 255, 255, 255) }, + { RoadShieldGreenText, dp::Color(255, 255, 255, 255) }, + { RoadShieldUKGreenText, dp::Color(255, 204, 102, 255) }, + { RoadShieldBlueBackground, dp::Color(46, 111, 201, 255) }, + { RoadShieldGreenBackground, dp::Color(34, 114, 59, 255) }, } }, }; diff --git a/drape_frontend/color_constants.hpp b/drape_frontend/color_constants.hpp index a2d62be0d7..fcb2ca52f4 100644 --- a/drape_frontend/color_constants.hpp +++ b/drape_frontend/color_constants.hpp @@ -36,7 +36,16 @@ enum ColorConstant TrafficUnknown, TrafficArrowLight, TrafficArrowDark, - TrafficOutline + TrafficOutline, + RoadShieldAddText, + RoadShieldAddTextOutline, + RoadShieldUSInterstateText, + RoadShieldUSHighwayText, + RoadShieldBlueText, + RoadShieldGreenText, + RoadShieldUKGreenText, + RoadShieldBlueBackground, + RoadShieldGreenBackground, }; dp::Color GetColorConstant(MapStyle style, ColorConstant constant); diff --git a/drape_frontend/colored_symbol_shape.cpp b/drape_frontend/colored_symbol_shape.cpp new file mode 100644 index 0000000000..fac1b0590b --- /dev/null +++ b/drape_frontend/colored_symbol_shape.cpp @@ -0,0 +1,226 @@ +#include "drape_frontend/colored_symbol_shape.hpp" +#include "drape_frontend/visual_params.hpp" + +#include "drape/utils/vertex_decl.hpp" +#include "drape/glsl_types.hpp" +#include "drape/glsl_func.hpp" +#include "drape/overlay_handle.hpp" +#include "drape/shader_def.hpp" +#include "drape/attribute_provider.hpp" +#include "drape/texture_manager.hpp" +#include "drape/glstate.hpp" +#include "drape/batcher.hpp" + +namespace df +{ + +ColoredSymbolShape::ColoredSymbolShape(m2::PointD const & mercatorPt, ColoredSymbolViewParams const & params, + TileKey const & tileKey, uint32_t textIndex, bool needOverlay, + int displacementMode, uint16_t specialModePriority) + : m_point(mercatorPt) + , m_params(params) + , m_tileCoords(tileKey.GetTileCoords()) + , m_textIndex(textIndex) + , m_needOverlay(needOverlay) + , m_displacementMode(displacementMode) + , m_specialModePriority(specialModePriority) +{} + +void ColoredSymbolShape::Draw(ref_ptr batcher, ref_ptr textures) const +{ + dp::TextureManager::ColorRegion colorRegion; + textures->GetColorRegion(m_params.m_color, colorRegion); + m2::PointF const & colorUv = colorRegion.GetTexRect().Center(); + + dp::TextureManager::ColorRegion outlineColorRegion; + textures->GetColorRegion(m_params.m_outlineColor, outlineColorRegion); + m2::PointF const & outlineUv = outlineColorRegion.GetTexRect().Center(); + + using V = gpu::ColoredSymbolVertex; + V::TTexCoord const uv(colorUv.x, colorUv.y, 0.0f, 0.0f); + V::TTexCoord const uvOutline(outlineUv.x, outlineUv.y, 0.0f, 0.0f); + + glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(m_point, m_params.m_tileCenter, kShapeCoordScalar)); + glsl::vec3 const position = glsl::vec3(pt, m_params.m_depth); + + buffer_vector buffer; + + m2::PointU pixelSize; + if (m_params.m_shape == ColoredSymbolViewParams::Shape::Circle) + { + pixelSize = m2::PointU(2 * static_cast(m_params.m_radiusInPixels), + 2 * static_cast(m_params.m_radiusInPixels)); + // Here we use an equilateral triangle to render circle (incircle of a triangle). + static float const kSqrt3 = sqrt(3.0f); + float r = m_params.m_radiusInPixels - m_params.m_outlineWidth; + + buffer.push_back(V(position, V::TNormal(-r * kSqrt3, -r, r, 1.0f), uv)); + buffer.push_back(V(position, V::TNormal(r * kSqrt3, -r, r, 1.0f), uv)); + buffer.push_back(V(position, V::TNormal(0.0f, 2.0f * r, r, 1.0f), uv)); + + if (m_params.m_outlineWidth >= 1e-5) + { + r = m_params.m_radiusInPixels; + buffer.push_back(V(position, V::TNormal(-r * kSqrt3, -r, r, 1.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(r * kSqrt3, -r, r, 1.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(0.0f, 2.0f * r, r, 1.0f), uvOutline)); + } + } + else if (m_params.m_shape == ColoredSymbolViewParams::Shape::Rectangle) + { + pixelSize = m2::PointU(static_cast(m_params.m_sizeInPixels.x), + static_cast(m_params.m_sizeInPixels.y)); + float const halfWidth = 0.5f * m_params.m_sizeInPixels.x; + float const halfHeight = 0.5f * m_params.m_sizeInPixels.y; + float const v = halfWidth * halfWidth + halfHeight * halfHeight; + float const halfWidthInside = halfWidth - m_params.m_outlineWidth; + float const halfHeightInside = halfHeight - m_params.m_outlineWidth; + + buffer.push_back(V(position, V::TNormal(-halfWidthInside, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, -halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthInside, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthInside, -halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, -halfHeightInside, v, 0.0f), uv)); + + if (m_params.m_outlineWidth >= 1e-5) + { + buffer.push_back(V(position, V::TNormal(-halfWidth, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, -halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidth, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidth, -halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, -halfHeight, v, 0.0f), uvOutline)); + } + } + else if (m_params.m_shape == ColoredSymbolViewParams::Shape::RoundedRectangle) + { + pixelSize = m2::PointU(static_cast(m_params.m_sizeInPixels.x), + static_cast(m_params.m_sizeInPixels.y)); + float const halfWidth = 0.5f * m_params.m_sizeInPixels.x; + float const halfHeight = 0.5f * m_params.m_sizeInPixels.y; + float const halfWidthBody = halfWidth - m_params.m_radiusInPixels; + float const halfHeightBody = halfHeight - m_params.m_radiusInPixels; + float const v = halfWidth * halfWidth + halfHeight * halfHeight; + float const halfWidthInside = halfWidth - m_params.m_outlineWidth; + float const halfHeightInside = halfHeight - m_params.m_outlineWidth; + + if (halfWidthBody > 0.0f && halfHeightInside > 0.0f) + { + buffer.push_back(V(position, V::TNormal(-halfWidthBody, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, -halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthBody, halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthBody, -halfHeightInside, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, -halfHeightInside, v, 0.0f), uv)); + } + + if (halfHeightBody > 0.0f && halfHeightBody > 0.0f) + { + buffer.push_back(V(position, V::TNormal(-halfWidthInside, halfHeightBody, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, -halfHeightBody, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, halfHeightBody, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthInside, halfHeightBody, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(-halfWidthInside, -halfHeightBody, v, 0.0f), uv)); + buffer.push_back(V(position, V::TNormal(halfWidthInside, -halfHeightBody, v, 0.0f), uv)); + } + + // Here we use an right triangle to render a quarter of circle. + static float const kSqrt2 = sqrt(2.0f); + float r = m_params.m_radiusInPixels - m_params.m_outlineWidth; + V::TTexCoord uv2(uv.x, uv.y, -halfWidthBody, halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, r * kSqrt2, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(-r * kSqrt2, 0.0, r, 0.0f), uv2)); + + uv2 = V::TTexCoord(uv.x, uv.y, halfWidthBody, halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(r * kSqrt2, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, r * kSqrt2, r, 0.0f), uv2)); + + uv2 = V::TTexCoord(uv.x, uv.y, halfWidthBody, -halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, -r * kSqrt2, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(r * kSqrt2, 0.0, r, 0.0f), uv2)); + + uv2 = V::TTexCoord(uv.x, uv.y, -halfWidthBody, -halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(-r * kSqrt2, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, -r * kSqrt2, r, 0.0f), uv2)); + + if (m_params.m_outlineWidth >= 1e-5) + { + if (halfWidthBody > 0.0f && halfHeight > 0.0f) + { + buffer.push_back(V(position, V::TNormal(-halfWidthBody, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, -halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidthBody, halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidthBody, -halfHeight, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidthBody, -halfHeight, v, 0.0f), uvOutline)); + } + + if (halfWidth > 0.0f && halfHeightBody > 0.0f) + { + buffer.push_back(V(position, V::TNormal(-halfWidth, halfHeightBody, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, -halfHeightBody, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, halfHeightBody, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidth, halfHeightBody, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(-halfWidth, -halfHeightBody, v, 0.0f), uvOutline)); + buffer.push_back(V(position, V::TNormal(halfWidth, -halfHeightBody, v, 0.0f), uvOutline)); + } + + r = m_params.m_radiusInPixels; + V::TTexCoord const uvOutline2(outlineUv.x, outlineUv.y, -halfWidthBody, halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uvOutline2)); + buffer.push_back(V(position, V::TNormal(0.0, r * kSqrt2, r, 0.0f), uvOutline2)); + buffer.push_back(V(position, V::TNormal(-r * kSqrt2, 0.0, r, 0.0f), uvOutline2)); + + uv2 = V::TTexCoord(outlineUv.x, outlineUv.y, halfWidthBody, halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(r * kSqrt2, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, r * kSqrt2, r, 0.0f), uv2)); + + uv2 = V::TTexCoord(outlineUv.x, outlineUv.y, halfWidthBody, -halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, -r * kSqrt2, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(r * kSqrt2, 0.0, r, 0.0f), uv2)); + + uv2 = V::TTexCoord(outlineUv.x, outlineUv.y, -halfWidthBody, -halfHeightBody); + buffer.push_back(V(position, V::TNormal(0.0, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(-r * kSqrt2, 0.0, r, 0.0f), uv2)); + buffer.push_back(V(position, V::TNormal(0.0, -r * kSqrt2, r, 0.0f), uv2)); + } + } + + if (buffer.empty()) + return; + + auto const overlayId = dp::OverlayID(m_params.m_featureID, m_tileCoords, m_textIndex); + std::string const debugName = strings::to_string(m_params.m_featureID.m_index) + "-" + + strings::to_string(m_textIndex); + + drape_ptr handle = m_needOverlay ? + make_unique_dp(overlayId, dp::Center, m_point, pixelSize, GetOverlayPriority(), + true /* isBound */, debugName, true /* isBillboard */) : nullptr; + + dp::GLState state(gpu::COLORED_SYMBOL_PROGRAM, dp::GLState::OverlayLayer); + state.SetProgram3dIndex(gpu::COLORED_SYMBOL_BILLBOARD_PROGRAM); + state.SetColorTexture(colorRegion.GetTexture()); + state.SetDepthFunction(gl_const::GLLess); + + dp::AttributeProvider provider(1, static_cast(buffer.size())); + provider.InitStream(0, gpu::ColoredSymbolVertex::GetBindingInfo(), make_ref(buffer.data())); + batcher->InsertTriangleList(state, make_ref(&provider), move(handle)); +} + +uint64_t ColoredSymbolShape::GetOverlayPriority() const +{ + // Special displacement mode. + if ((m_displacementMode & dp::displacement::kDefaultMode) == 0) + return dp::CalculateSpecialModePriority(m_specialModePriority); + + return dp::CalculateOverlayPriority(m_params.m_minVisibleScale, m_params.m_rank, m_params.m_depth); +} + +} // namespace df diff --git a/drape_frontend/colored_symbol_shape.hpp b/drape_frontend/colored_symbol_shape.hpp new file mode 100644 index 0000000000..2f93323fe0 --- /dev/null +++ b/drape_frontend/colored_symbol_shape.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "drape_frontend/map_shape.hpp" +#include "drape_frontend/shape_view_params.hpp" + +#include "drape/constants.hpp" + +namespace df +{ + +class ColoredSymbolShape : public MapShape +{ +public: + ColoredSymbolShape(m2::PointD const & mercatorPt, ColoredSymbolViewParams const & params, + TileKey const & tileKey, uint32_t textIndex, bool needOverlay = true, + int displacementMode = dp::displacement::kAllModes, + uint16_t specialModePriority = 0xFFFF); + void Draw(ref_ptr batcher, ref_ptr textures) const override; + MapShapeType GetType() const override { return MapShapeType::OverlayType; } + +private: + uint64_t GetOverlayPriority() const; + + m2::PointD const m_point; + ColoredSymbolViewParams m_params; + m2::PointI const m_tileCoords; + uint32_t const m_textIndex; + bool const m_needOverlay; + int const m_displacementMode; + uint16_t const m_specialModePriority; +}; + +} // namespace df diff --git a/drape_frontend/drape_api_builder.cpp b/drape_frontend/drape_api_builder.cpp index a52335488f..d650653b61 100644 --- a/drape_frontend/drape_api_builder.cpp +++ b/drape_frontend/drape_api_builder.cpp @@ -1,5 +1,5 @@ #include "drape_frontend/drape_api_builder.hpp" -#include "drape_frontend/circle_shape.hpp" +#include "drape_frontend/colored_symbol_shape.hpp" #include "drape_frontend/gui/gui_text.hpp" #include "drape_frontend/line_shape.hpp" #include "drape_frontend/shape_view_params.hpp" @@ -74,14 +74,18 @@ void DrapeApiBuilder::BuildLines(DrapeApi::TLines const & lines, ref_ptrm_center; cvp.m_depth = 0.0f; cvp.m_minVisibleScale = 1; + cvp.m_shape = ColoredSymbolViewParams::Shape::Circle; cvp.m_color = data.m_color; - cvp.m_radius = data.m_width * 2.0f; + cvp.m_radiusInPixels = data.m_width * 2.0f; for (m2::PointD const & pt : data.m_points) - CircleShape(m2::PointF(pt), cvp, false /* need overlay */).Draw(make_ref(&batcher), textures); + { + ColoredSymbolShape(m2::PointF(pt), cvp, TileKey(), 0 /* textIndex */, + false /* need overlay */).Draw(make_ref(&batcher), textures); + } } if (data.m_markPoints || data.m_showId) diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 2e42ba7a55..289a80cfb8 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -166,7 +166,7 @@ public: void SetDisplacementMode(int mode); - using TRequestSymbolsSizeCallback = function const &)>; + using TRequestSymbolsSizeCallback = function const &)>; void RequestSymbolsSize(vector const & symbols, TRequestSymbolsSizeCallback const & callback); diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 6f2e85a753..47ccfd2332 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -43,8 +43,8 @@ SOURCES += \ backend_renderer.cpp \ base_renderer.cpp \ batch_merge_helper.cpp \ - circle_shape.cpp \ color_constants.cpp \ + colored_symbol_shape.cpp \ drape_api.cpp \ drape_api_builder.cpp \ drape_api_renderer.cpp \ @@ -144,8 +144,8 @@ HEADERS += \ base_renderer.hpp \ batchers_pool.hpp \ batch_merge_helper.hpp \ - circle_shape.hpp \ color_constants.hpp \ + colored_symbol_shape.hpp \ drape_api.hpp \ drape_api_builder.hpp \ drape_api_renderer.hpp \ diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 21f764f83e..fe6925c54f 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -999,7 +999,7 @@ FeatureID FrontendRenderer::GetVisiblePOI(m2::RectD const & pixelRect) if (curDist < dist) { dist = curDist; - featureID = handle->GetFeatureID(); + featureID = handle->GetOverlayID().m_featureId; } } @@ -1097,8 +1097,9 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) RenderTrafficAndRouteLayer(modelView); } - // After this line we do not use depth buffer. + // After this line we do not use (almost) depth buffer. GLFunctions::glDisable(gl_const::GLDepthTest); + GLFunctions::glClearDepth(); if (m_selectionShape != nullptr) { diff --git a/drape_frontend/gui/choose_position_mark.cpp b/drape_frontend/gui/choose_position_mark.cpp index e08c350d28..a1896d9151 100644 --- a/drape_frontend/gui/choose_position_mark.cpp +++ b/drape_frontend/gui/choose_position_mark.cpp @@ -48,7 +48,7 @@ drape_ptr ChoosePositionMark::Draw(ref_ptr te { dp::TextureManager::SymbolRegion region; tex->GetSymbolRegion("cross_geoposition", region); - glsl::vec2 const halfSize = glsl::ToVec2(m2::PointD(region.GetPixelSize()) * 0.5); + glsl::vec2 const halfSize = glsl::ToVec2(region.GetPixelSize() * 0.5f); m2::RectF const texRect = region.GetTexRect(); ASSERT_EQUAL(m_position.m_anchor, dp::Center, ()); diff --git a/drape_frontend/gui/compass.cpp b/drape_frontend/gui/compass.cpp index 2ff4222656..18feec3b4a 100644 --- a/drape_frontend/gui/compass.cpp +++ b/drape_frontend/gui/compass.cpp @@ -92,7 +92,7 @@ drape_ptr Compass::Draw(m2::PointF & compassSize, ref_ptrGetSymbolRegion("compass-image", region); - glsl::vec2 halfSize = glsl::ToVec2(m2::PointD(region.GetPixelSize()) * 0.5); + glsl::vec2 halfSize = glsl::ToVec2(region.GetPixelSize() * 0.5f); m2::RectF texRect = region.GetTexRect(); ASSERT_EQUAL(m_position.m_anchor, dp::Center, ()); diff --git a/drape_frontend/gui/gui_text.cpp b/drape_frontend/gui/gui_text.cpp index 3fa4883ee4..b28c1559a1 100644 --- a/drape_frontend/gui/gui_text.cpp +++ b/drape_frontend/gui/gui_text.cpp @@ -22,7 +22,7 @@ namespace glsl::vec2 GetNormalsAndMask(dp::TextureManager::GlyphRegion const & glyph, float textRatio, array & normals, array & maskTexCoord) { - m2::PointF const pixelSize = m2::PointF(glyph.GetPixelSize()) * textRatio; + m2::PointF const pixelSize = glyph.GetPixelSize() * textRatio; m2::RectF const & r = glyph.GetTexRect(); float const xOffset = glyph.GetOffsetX() * textRatio; @@ -430,7 +430,7 @@ m2::PointF MutableLabel::GetAvarageSize() const for (TAlphabetNode const & node : m_alphabet) { dp::TextureManager::GlyphRegion const & reg = node.second; - m2::PointF size = m2::PointF(reg.GetPixelSize()) * m_textRatio; + m2::PointF size = reg.GetPixelSize() * m_textRatio; w += size.x; h = max(h, size.y); } diff --git a/drape_frontend/gui/layer_render.cpp b/drape_frontend/gui/layer_render.cpp index 72293db5ee..1785db4bee 100644 --- a/drape_frontend/gui/layer_render.cpp +++ b/drape_frontend/gui/layer_render.cpp @@ -109,7 +109,7 @@ bool LayerRenderer::OnTouchDown(m2::RectD const & touchArea) m_activeOverlay = r.second->ProcessTapEvent(touchArea); if (m_activeOverlay != nullptr) { - m_activeOverlayId = m_activeOverlay->GetFeatureID(); + m_activeOverlayId = m_activeOverlay->GetOverlayID().m_featureId; m_activeOverlay->OnTapBegin(); return true; } diff --git a/drape_frontend/gui/ruler_helper.cpp b/drape_frontend/gui/ruler_helper.cpp index 748831b766..13f1dc9f22 100644 --- a/drape_frontend/gui/ruler_helper.cpp +++ b/drape_frontend/gui/ruler_helper.cpp @@ -204,7 +204,7 @@ void RulerHelper::GetTextInitInfo(string & alphabet, uint32_t & size) const { size_t stringSize = strlen(v.m_s); result = max(result, stringSize); - for (int i = 0; i < stringSize; ++i) + for (size_t i = 0; i < stringSize; ++i) symbols.insert(v.m_s[i]); }; diff --git a/drape_frontend/gui/shape.cpp b/drape_frontend/gui/shape.cpp index 89d496b0ae..e7f78536cb 100644 --- a/drape_frontend/gui/shape.cpp +++ b/drape_frontend/gui/shape.cpp @@ -174,7 +174,7 @@ ref_ptr ShapeRenderer::FindHandle(FeatureID const & id) ref_ptr resultHandle = nullptr; ForEachShapeInfo([&resultHandle, &id](ShapeControl::ShapeInfo & shapeInfo) { - if (shapeInfo.m_handle->GetFeatureID() == id) + if (shapeInfo.m_handle->GetOverlayID().m_featureId == id) resultHandle = make_ref(shapeInfo.m_handle); }); diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index a861ec4906..9498960f6f 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -978,7 +978,7 @@ private: class RequestSymbolsSizeMessage : public Message { public: - using TRequestSymbolsSizeCallback = function const &)>; + using TRequestSymbolsSizeCallback = function const &)>; RequestSymbolsSizeMessage(vector const & symbols, TRequestSymbolsSizeCallback const & callback) @@ -990,7 +990,7 @@ public: vector const & GetSymbols() const { return m_symbols; } - void InvokeCallback(vector const & sizes) + void InvokeCallback(vector const & sizes) { if (m_callback != nullptr) m_callback(sizes); diff --git a/drape_frontend/my_position.cpp b/drape_frontend/my_position.cpp index d7d480bcd1..081166d9d9 100644 --- a/drape_frontend/my_position.cpp +++ b/drape_frontend/my_position.cpp @@ -192,7 +192,7 @@ void MyPosition::CacheSymbol(dp::TextureManager::SymbolRegion const & symbol, EMyPositionPart part) { m2::RectF const & texRect = symbol.GetTexRect(); - m2::PointF const halfSize = m2::PointF(symbol.GetPixelSize()) * 0.5f; + m2::PointF const halfSize = symbol.GetPixelSize() * 0.5f; Vertex data[4] = { diff --git a/drape_frontend/path_symbol_shape.cpp b/drape_frontend/path_symbol_shape.cpp index d2220a9a08..b65cce29c4 100644 --- a/drape_frontend/path_symbol_shape.cpp +++ b/drape_frontend/path_symbol_shape.cpp @@ -27,9 +27,9 @@ void PathSymbolShape::Draw(ref_ptr batcher, ref_ptrGetSymbolRegion(m_params.m_symbolName, region); m2::RectF const & rect = region.GetTexRect(); - m2::PointU pixelSize = region.GetPixelSize(); - float halfW = pixelSize.x / 2.0f; - float halfH = pixelSize.y / 2.0f; + m2::PointF pixelSize = region.GetPixelSize(); + float halfW = 0.5f * pixelSize.x; + float halfH = 0.5f * pixelSize.y; gpu::TSolidTexVertexBuffer buffer; diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp index c3202949c5..80548b7bd1 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(FeatureID const & id, m2::SharedSpline const & spl, + PathTextHandle(dp::OverlayID const & id, m2::SharedSpline const & spl, df::SharedTextLayout const & layout, - float mercatorOffset, float depth, - uint32_t textIndex, uint64_t priority, - uint64_t priorityFollowingMode, int fixedHeight, + float mercatorOffset, float depth, uint32_t textIndex, + uint64_t priority, uint64_t priorityFollowingMode, int fixedHeight, ref_ptr textureManager, bool isBillboard) - : TextHandle(id, layout->GetText(), dp::Center, priority, fixedHeight, textureManager, isBillboard) + : TextHandle(id, layout->GetText(), dp::Center, priority, fixedHeight, + textureManager, isBillboard) , m_spline(spl) , m_layout(layout) , m_textIndex(textIndex) @@ -220,10 +220,12 @@ private: namespace df { -PathTextShape::PathTextShape(m2::SharedSpline const & spline, - PathTextViewParams const & params) +PathTextShape::PathTextShape(m2::SharedSpline const & spline, PathTextViewParams const & params, + TileKey const & tileKey, uint32_t baseTextIndex) : m_spline(spline) , m_params(params) + , m_tileCoords(tileKey.GetTileCoords()) + , m_baseTextIndex(baseTextIndex) {} uint64_t PathTextShape::GetOverlayPriority(uint32_t textIndex, bool followingMode) const @@ -272,8 +274,9 @@ void PathTextShape::DrawPathTextPlain(ref_ptr textures, provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data())); - drape_ptr handle = make_unique_dp(m_params.m_featureID, m_spline, layoutPtr, offset, - m_params.m_depth, textIndex, + dp::OverlayID const overlayId = dp::OverlayID(m_params.m_featureID, m_tileCoords, m_baseTextIndex + textIndex); + drape_ptr handle = make_unique_dp(overlayId, m_spline, + layoutPtr, offset, m_params.m_depth, textIndex, GetOverlayPriority(textIndex, false /* followingMode */), GetOverlayPriority(textIndex, true /* followingMode */), layoutPtr->GetFixedHeight(), @@ -314,7 +317,8 @@ void PathTextShape::DrawPathTextOutlined(ref_ptr textures, provider.InitStream(0, gpu::TextOutlinedStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data())); - drape_ptr handle = make_unique_dp(m_params.m_featureID, m_spline, layoutPtr, offset, + dp::OverlayID const overlayId = dp::OverlayID(m_params.m_featureID, m_tileCoords, m_baseTextIndex + textIndex); + drape_ptr handle = make_unique_dp(overlayId, m_spline, layoutPtr, offset, m_params.m_depth, textIndex, GetOverlayPriority(textIndex, false /* followingMode */), GetOverlayPriority(textIndex, true /* followingMode */), diff --git a/drape_frontend/path_text_shape.hpp b/drape_frontend/path_text_shape.hpp index e1b6c1a4a1..27c942f76b 100644 --- a/drape_frontend/path_text_shape.hpp +++ b/drape_frontend/path_text_shape.hpp @@ -13,7 +13,8 @@ class PathTextLayout; class PathTextShape : public MapShape { public: - PathTextShape(m2::SharedSpline const & spline, PathTextViewParams const & params); + PathTextShape(m2::SharedSpline const & spline, PathTextViewParams const & params, + TileKey const & tileKey, uint32_t baseTextIndex); void Draw(ref_ptr batcher, ref_ptr textures) const override; MapShapeType GetType() const override { return MapShapeType::OverlayType; } @@ -31,6 +32,8 @@ private: m2::SharedSpline m_spline; PathTextViewParams m_params; + m2::PointI const m_tileCoords; + uint32_t const m_baseTextIndex; }; } // namespace df diff --git a/drape_frontend/poi_symbol_shape.cpp b/drape_frontend/poi_symbol_shape.cpp index 1fd1b13495..d325d434dd 100644 --- a/drape_frontend/poi_symbol_shape.cpp +++ b/drape_frontend/poi_symbol_shape.cpp @@ -31,7 +31,7 @@ void Batch(ref_ptr batcher, drape_ptr && han dp::TextureManager::SymbolRegion const & symbolRegion, dp::TextureManager::ColorRegion const & colorRegion) { - m2::PointU const pixelSize = symbolRegion.GetPixelSize(); + m2::PointF const pixelSize = symbolRegion.GetPixelSize(); m2::PointF const halfSize(pixelSize.x * 0.5f, pixelSize.y * 0.5f); m2::RectF const & texRect = symbolRegion.GetTexRect(); @@ -63,7 +63,7 @@ void Batch(ref_ptr batcher, drape_ptr && han dp::TextureManager::SymbolRegion const & symbolRegion, dp::TextureManager::ColorRegion const & colorRegion) { - m2::PointU const pixelSize = symbolRegion.GetPixelSize(); + m2::PointF const pixelSize = symbolRegion.GetPixelSize(); m2::PointF const halfSize(pixelSize.x * 0.5f, pixelSize.y * 0.5f); m2::RectF const & texRect = symbolRegion.GetTexRect(); glsl::vec2 const maskColorCoords = glsl::ToVec2(colorRegion.GetTexRect().Center()); @@ -95,12 +95,15 @@ void Batch(ref_ptr batcher, drape_ptr && han namespace df { -PoiSymbolShape::PoiSymbolShape(m2::PointF const & mercatorPt, PoiSymbolViewParams const & params, +PoiSymbolShape::PoiSymbolShape(m2::PointD const & mercatorPt, PoiSymbolViewParams const & params, + TileKey const & tileKey, uint32_t textIndex, int displacementMode, uint16_t specialModePriority) : m_pt(mercatorPt) , m_params(params) , m_displacementMode(displacementMode) , m_specialModePriority(specialModePriority) + , m_tileCoords(tileKey.GetTileCoords()) + , m_textIndex(textIndex) {} void PoiSymbolShape::Draw(ref_ptr batcher, ref_ptr textures) const @@ -110,9 +113,10 @@ void PoiSymbolShape::Draw(ref_ptr batcher, ref_ptr handle = make_unique_dp(m_params.m_id, + dp::OverlayID overlayId = dp::OverlayID(m_params.m_id, m_tileCoords, m_textIndex); + drape_ptr handle = make_unique_dp(overlayId, dp::Center, m_pt, pixelSize, GetOverlayPriority(), diff --git a/drape_frontend/poi_symbol_shape.hpp b/drape_frontend/poi_symbol_shape.hpp index d17fd51614..ed09476752 100644 --- a/drape_frontend/poi_symbol_shape.hpp +++ b/drape_frontend/poi_symbol_shape.hpp @@ -11,7 +11,8 @@ namespace df class PoiSymbolShape : public MapShape { public: - PoiSymbolShape(m2::PointF const & mercatorPt, PoiSymbolViewParams const & params, + PoiSymbolShape(m2::PointD const & mercatorPt, PoiSymbolViewParams const & params, + TileKey const & tileKey, uint32_t textIndex, int displacementMode = dp::displacement::kAllModes, uint16_t specialModePriority = 0xFFFF); @@ -21,10 +22,12 @@ public: private: uint64_t GetOverlayPriority() const; - m2::PointF const m_pt; + m2::PointD const m_pt; PoiSymbolViewParams const m_params; int const m_displacementMode; uint16_t const m_specialModePriority; + m2::PointI const m_tileCoords; + uint32_t const m_textIndex; }; } // namespace df diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index ea9633c380..5e2260d4fc 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -94,8 +94,18 @@ void RenderGroup::Render(ScreenBase const & screen) m_uniforms.SetMatrix4x4Value("modelView", mv.m_data); } - int programIndex = m_state.GetProgramIndex(); - int program3dIndex = m_state.GetProgram3dIndex(); + int const programIndex = m_state.GetProgramIndex(); + int const program3dIndex = m_state.GetProgram3dIndex(); + + if (m_state.GetDepthLayer() == dp::GLState::OverlayLayer) + { + if (programIndex == gpu::COLORED_SYMBOL_PROGRAM || + programIndex == gpu::COLORED_SYMBOL_BILLBOARD_PROGRAM) + GLFunctions::glEnable(gl_const::GLDepthTest); + else + GLFunctions::glDisable(gl_const::GLDepthTest); + } + auto const & params = df::VisualParams::Instance().GetGlyphVisualParams(); if (programIndex == gpu::TEXT_OUTLINED_PROGRAM || program3dIndex == gpu::TEXT_OUTLINED_BILLBOARD_PROGRAM) diff --git a/drape_frontend/route_shape.cpp b/drape_frontend/route_shape.cpp index 779927fbda..7438e6ff4e 100644 --- a/drape_frontend/route_shape.cpp +++ b/drape_frontend/route_shape.cpp @@ -87,7 +87,7 @@ void GenerateJoinsTriangles(glsl::vec3 const & pivot, vector const & float const kEps = 1e-5; size_t const trianglesCount = normals.size() / 3; float const side = isLeft ? kLeftSide : kRightSide; - for (int j = 0; j < trianglesCount; j++) + for (size_t j = 0; j < trianglesCount; j++) { glsl::vec3 const len1 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j]) < kEps ? kCenter : side); glsl::vec3 const len2 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j + 1]) < kEps ? kCenter : side); @@ -115,7 +115,7 @@ void GenerateArrowsTriangles(glsl::vec4 const & pivot, vector const bool normalizedUV, RouteShape::TArrowGeometryBuffer & joinsGeometry) { size_t const trianglesCount = normals.size() / 3; - for (int j = 0; j < trianglesCount; j++) + for (size_t j = 0; j < trianglesCount; j++) { joinsGeometry.push_back(RouteShape::AV(pivot, normals[3 * j], normalizedUV ? GetUV(texRect, uv[3 * j]) : uv[3 * j])); @@ -154,7 +154,7 @@ void RouteShape::PrepareGeometry(vector const & path, m2::PointD con for (int i = static_cast(segments.size() - 1); i >= 0; i--) { UpdateNormals(&segments[i], (i > 0) ? &segments[i - 1] : nullptr, - (i < segments.size() - 1) ? &segments[i + 1] : nullptr); + (i < static_cast(segments.size()) - 1) ? &segments[i + 1] : nullptr); // Generate main geometry. m2::PointD const startPt = MapShape::ConvertToLocal(glsl::FromVec2(segments[i].m_points[StartPoint]), @@ -221,7 +221,7 @@ void RouteShape::PrepareGeometry(vector const & path, m2::PointD con true, joinsGeometry); } - if (i == segments.size() - 1) + if (i == static_cast(segments.size()) - 1) { vector normals; normals.reserve(24); @@ -361,7 +361,7 @@ void RouteShape::CacheRouteSign(ref_ptr mng, RouteSignData & mng->GetSymbolRegion(routeSignData.m_isStart ? "route_from" : "route_to", symbol); m2::RectF const & texRect = symbol.GetTexRect(); - m2::PointF halfSize = m2::PointF(symbol.GetPixelSize()) * 0.5f; + m2::PointF halfSize = symbol.GetPixelSize() * 0.5f; glsl::vec4 const pivot = glsl::vec4(0.0f /* x */, 0.0f /* y */, 0.0f /* depth */, 0.0f /* pivot z */); gpu::SolidTexturingVertex data[4]= diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 4939725eee..65b66549bf 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -69,7 +69,7 @@ void ExtractTrafficGeometry(FeatureType const & f, df::RoadClass const & roadCla int const index = zoomLevel - kFirstZoomInAverageSegments; ASSERT_GREATER_OR_EQUAL(index, 0, ()); - ASSERT_LESS(index, kAverageSegmentsCount.size(), ()); + ASSERT_LESS(index, static_cast(kAverageSegmentsCount.size()), ()); segments.reserve(kAverageSegmentsCount[index]); for (uint16_t segIndex = 0; segIndex + 1 < static_cast(polyline.GetSize()); ++segIndex) @@ -225,7 +225,7 @@ void RuleDrawer::operator()(FeatureType const & f) auto insertShape = [this, &minVisibleScale](drape_ptr && shape) { int const index = static_cast(shape->GetType()); - ASSERT_LESS(index, m_mapShapes.size(), ()); + ASSERT_LESS(index, static_cast(m_mapShapes.size()), ()); shape->SetFeatureMinZoom(minVisibleScale); m_mapShapes[index].push_back(move(shape)); @@ -300,7 +300,7 @@ void RuleDrawer::operator()(FeatureType const & f) minVisibleScale = feature::GetMinDrawableScale(f); bool const generateOutline = (zoomLevel >= kOutlineMinZoomLevel); - ApplyAreaFeature apply(m_globalRect.Center(), insertShape, f.GetID(), m_globalRect, + ApplyAreaFeature apply(m_context->GetTileKey(), insertShape, f.GetID(), isBuilding, areaMinHeight, areaHeight, minVisibleScale, f.GetRank(), generateOutline, s.GetCaptionDescription()); f.ForEachTriangle(apply, zoomLevel); @@ -316,9 +316,9 @@ void RuleDrawer::operator()(FeatureType const & f) } else if (s.LineStyleExists()) { - ApplyLineFeature apply(m_globalRect.Center(), m_currentScaleGtoP, insertShape, f.GetID(), - m_globalRect, minVisibleScale, f.GetRank(), s.GetCaptionDescription(), - zoomLevel, f.GetPointsCount()); + ApplyLineFeature apply(m_context->GetTileKey(), insertShape, f.GetID(), + m_currentScaleGtoP, minVisibleScale, f.GetRank(), + s.GetCaptionDescription(), f.GetPointsCount()); f.ForEachPoint(apply, zoomLevel); if (CheckCancelled()) @@ -326,7 +326,8 @@ void RuleDrawer::operator()(FeatureType const & f) if (apply.HasGeometry()) s.ForEachRule(bind(&ApplyLineFeature::ProcessRule, &apply, _1)); - apply.Finish(); + + apply.Finish(ftypes::GetRoadShields(f)); if (m_trafficEnabled && zoomLevel >= kRoadClass0ZoomLevel) { @@ -370,7 +371,7 @@ void RuleDrawer::operator()(FeatureType const & f) ASSERT(s.PointStyleExists(), ()); minVisibleScale = feature::GetMinDrawableScale(f); - ApplyPointFeature apply(m_globalRect.Center(), insertShape, f.GetID(), minVisibleScale, f.GetRank(), + ApplyPointFeature apply(m_context->GetTileKey(), insertShape, f.GetID(), minVisibleScale, f.GetRank(), s.GetCaptionDescription(), 0.0f /* posZ */); apply.SetHotelData(ExtractHotelData(f)); f.ForEachPoint([&apply](m2::PointD const & pt) { apply(pt, false /* hasArea */); }, zoomLevel); diff --git a/drape_frontend/shape_view_params.hpp b/drape_frontend/shape_view_params.hpp index 6341e80829..f364c2644f 100644 --- a/drape_frontend/shape_view_params.hpp +++ b/drape_frontend/shape_view_params.hpp @@ -36,17 +36,6 @@ struct PoiSymbolViewParams : CommonViewParams bool m_obsoleteInEditor = false; }; -struct CircleViewParams : CommonViewParams -{ - CircleViewParams(FeatureID const & id) : m_id(id) {} - - FeatureID m_id; - dp::Color m_color; - float m_radius = 0.0f; - bool m_hasArea = false; - bool m_createdByEditor = false; -}; - struct AreaViewParams : CommonViewParams { dp::Color m_color; @@ -77,12 +66,15 @@ struct TextViewParams : CommonViewParams string m_secondaryText; dp::Anchor m_anchor; m2::PointF m_primaryOffset; + m2::PointF m_secondaryOffset; bool m_primaryOptional = false; bool m_secondaryOptional = false; bool m_hasArea = false; bool m_createdByEditor = false; uint32_t m_extendingSize = 0; float m_posZ = 0.0f; + bool m_limitedText = false; + m2::PointF m_limits; }; struct PathTextViewParams : CommonViewParams @@ -102,4 +94,20 @@ struct PathSymbolViewParams : CommonViewParams float m_baseGtoPScale = 1.0f; }; +struct ColoredSymbolViewParams : CommonViewParams +{ + enum class Shape + { + Rectangle, Circle, RoundedRectangle + }; + + FeatureID m_featureID; + Shape m_shape = Shape::Circle; + dp::Color m_color; + dp::Color m_outlineColor; + float m_radiusInPixels = 0.0f; + m2::PointF m_sizeInPixels; + float m_outlineWidth = 0.0f; +}; + } // namespace df diff --git a/drape_frontend/text_handle.cpp b/drape_frontend/text_handle.cpp index b6fe31913d..7177b66600 100644 --- a/drape_frontend/text_handle.cpp +++ b/drape_frontend/text_handle.cpp @@ -7,7 +7,7 @@ namespace df { -TextHandle::TextHandle(FeatureID const & id, strings::UniString const & text, +TextHandle::TextHandle(dp::OverlayID const & id, strings::UniString const & text, dp::Anchor anchor, uint64_t priority, int fixedHeight, ref_ptr textureManager, bool isBillboard) @@ -20,7 +20,7 @@ TextHandle::TextHandle(FeatureID const & id, strings::UniString const & text, , m_fixedHeight(fixedHeight) {} -TextHandle::TextHandle(FeatureID const & id, strings::UniString const & text, +TextHandle::TextHandle(dp::OverlayID const & id, strings::UniString const & text, dp::Anchor anchor, uint64_t priority, int fixedHeight, ref_ptr textureManager, gpu::TTextDynamicVertexBuffer && normals, @@ -83,7 +83,8 @@ void TextHandle::SetForceUpdateNormals(bool forceUpdate) const string TextHandle::GetOverlayDebugInfo() { ostringstream out; - out << "Text Priority(" << GetPriority() << ") " << GetFeatureID().m_index << " " << strings::ToUtf8(m_text); + out << "Text Priority(" << GetPriority() << ") " << GetOverlayID().m_featureId.m_index + << "-" << GetOverlayID().m_index << " " << strings::ToUtf8(m_text); return out.str(); } #endif diff --git a/drape_frontend/text_handle.hpp b/drape_frontend/text_handle.hpp index 848d70193a..8d8cd8456c 100644 --- a/drape_frontend/text_handle.hpp +++ b/drape_frontend/text_handle.hpp @@ -17,12 +17,12 @@ namespace df class TextHandle : public dp::OverlayHandle { public: - TextHandle(FeatureID const & id, strings::UniString const & text, + TextHandle(dp::OverlayID const & id, strings::UniString const & text, dp::Anchor anchor, uint64_t priority, int fixedHeight, ref_ptr textureManager, bool isBillboard = false); - TextHandle(FeatureID const & id, strings::UniString const & text, + TextHandle(dp::OverlayID const & id, strings::UniString const & text, dp::Anchor anchor, uint64_t priority, int fixedHeight, ref_ptr textureManager, gpu::TTextDynamicVertexBuffer && normals, diff --git a/drape_frontend/text_layout.cpp b/drape_frontend/text_layout.cpp index 219be61367..f0526dabc2 100644 --- a/drape_frontend/text_layout.cpp +++ b/drape_frontend/text_layout.cpp @@ -45,28 +45,26 @@ protected: gpu::TTextStaticVertexBuffer & m_buffer; }; -class StraigthTextGeometryGenerator : public TextGeometryGenerator +template +class StraightTextGeometryGenerator : public TParentGenerator { - typedef TextGeometryGenerator TBase; public: - StraigthTextGeometryGenerator(glsl::vec4 const & pivot, glsl::vec2 const & pixelOffset, - float textRatio, - dp::TextureManager::ColorRegion const & color, - gpu::TTextStaticVertexBuffer & staticBuffer, - gpu::TTextDynamicVertexBuffer & dynBuffer) - : TBase(color, staticBuffer) + template + StraightTextGeometryGenerator(glsl::vec4 const & pivot, glsl::vec2 const & pixelOffset, float textRatio, + gpu::TTextDynamicVertexBuffer & dynBuffer, + TParentGeneratorParams & ... parentGeneratorParams) + : TParentGenerator(parentGeneratorParams...) , m_pivot(pivot) , m_penPosition(pixelOffset) , m_buffer(dynBuffer) , m_textRatio(textRatio) - { - } + {} void operator()(dp::TextureManager::GlyphRegion const & glyph) { if (!glyph.IsValid()) return; - m2::PointF pixelSize = m2::PointF(glyph.GetPixelSize()) * m_textRatio; + m2::PointF pixelSize = glyph.GetPixelSize() * m_textRatio; float const xOffset = glyph.GetOffsetX() * m_textRatio; float const yOffset = glyph.GetOffsetY() * m_textRatio; @@ -77,7 +75,7 @@ public: if (m_isFirstGlyph) { m_isFirstGlyph = false; - m_penPosition += glsl::vec2(-xOffset, 0.0f); + m_penPosition.x -= (xOffset + dp::kSdfBorder * m_textRatio); } m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(xOffset, bottomVector))); @@ -86,7 +84,7 @@ public: m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(pixelSize.x + xOffset, upVector))); m_penPosition += glsl::vec2(glyph.GetAdvanceX() * m_textRatio, glyph.GetAdvanceY() * m_textRatio); - TBase::operator()(glyph); + TParentGenerator::operator()(glyph); } private: @@ -124,59 +122,6 @@ protected: gpu::TTextOutlinedStaticVertexBuffer & m_buffer; }; -class StraigthTextOutlinedGeometryGenerator : public TextOutlinedGeometryGenerator -{ - typedef TextOutlinedGeometryGenerator TBase; -public: - StraigthTextOutlinedGeometryGenerator(glsl::vec4 const & pivot, glsl::vec2 const & pixelOffset, - float textRatio, - dp::TextureManager::ColorRegion const & color, - dp::TextureManager::ColorRegion const & outline, - gpu::TTextOutlinedStaticVertexBuffer & staticBuffer, - gpu::TTextDynamicVertexBuffer & dynBuffer) - : TBase(color, outline, staticBuffer) - , m_pivot(pivot) - , m_penPosition(pixelOffset) - , m_buffer(dynBuffer) - , m_textRatio(textRatio) - { - } - - void operator()(dp::TextureManager::GlyphRegion const & glyph) - { - if (!glyph.IsValid()) - return; - m2::PointF pixelSize = m2::PointF(glyph.GetPixelSize()) * m_textRatio; - - float const xOffset = glyph.GetOffsetX() * m_textRatio; - float const yOffset = glyph.GetOffsetY() * m_textRatio; - - float const upVector = -static_cast(pixelSize.y) - yOffset; - float const bottomVector = -yOffset; - - if (m_isFirstGlyph) - { - m_isFirstGlyph = false; - m_penPosition += glsl::vec2(-xOffset, 0.0f); - } - - m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(xOffset, bottomVector))); - m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(xOffset, upVector))); - m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(pixelSize.x + xOffset, bottomVector))); - m_buffer.emplace_back(gpu::TextDynamicVertex(m_pivot, m_penPosition + glsl::vec2(pixelSize.x + xOffset, upVector))); - m_penPosition += glsl::vec2(glyph.GetAdvanceX() * m_textRatio, glyph.GetAdvanceY() * m_textRatio); - - TBase::operator()(glyph); - } - -private: - glsl::vec4 const & m_pivot; - glsl::vec2 m_penPosition; - gpu::TTextDynamicVertexBuffer & m_buffer; - float m_textRatio = 0.0f; - bool m_isFirstGlyph = true; -}; - ///Old code void SplitText(strings::UniString & visText, buffer_vector & delimIndexes) @@ -203,7 +148,7 @@ void SplitText(strings::UniString & visText, // don't do split like this: // xxxx // xxxxxxxxxxxx - if (4 * distance(visText.begin(), iPrev) <= count) + if (4 * distance(visText.begin(), iPrev) <= static_cast(count)) iPrev = visText.end(); else --iPrev; @@ -286,12 +231,11 @@ private: float m_penOffset; }; -void CalculateOffsets(dp::Anchor anchor, - float textRatio, +void CalculateOffsets(dp::Anchor anchor, float textRatio, dp::TextureManager::TGlyphsBuffer const & glyphs, buffer_vector const & delimIndexes, buffer_vector, 2> & result, - m2::PointU & pixelSize) + m2::PointF & pixelSize) { typedef pair TLengthAndHeight; buffer_vector lengthAndHeight; @@ -312,10 +256,15 @@ void CalculateOffsets(dp::Anchor anchor, continue; if (glyphIndex == start) - node.first += glyph.GetOffsetX(); + node.first -= glyph.GetOffsetX() * textRatio; - node.first += glyph.GetAdvanceX(); - node.second = max(node.second, glyph.GetPixelHeight() + glyph.GetAdvanceY()); + node.first += glyph.GetAdvanceX() * textRatio; + + float yAdvance = glyph.GetAdvanceY(); + if (glyph.GetOffsetY() < 0) + yAdvance += glyph.GetOffsetY(); + + node.second = max(node.second, (glyph.GetPixelHeight() + yAdvance) * textRatio); } maxLength = max(maxLength, node.first); summaryHeight += node.second; @@ -324,19 +273,16 @@ void CalculateOffsets(dp::Anchor anchor, ASSERT_EQUAL(delimIndexes.size(), lengthAndHeight.size(), ()); - maxLength *= textRatio; - summaryHeight *= textRatio; - XLayouter xL(anchor); YLayouter yL(anchor, summaryHeight); for (size_t index = 0; index < delimIndexes.size(); ++index) { TLengthAndHeight const & node = lengthAndHeight[index]; - result.push_back(make_pair(delimIndexes[index], glsl::vec2(xL(node.first * textRatio, maxLength), - yL(node.second * textRatio)))); + result.push_back(make_pair(delimIndexes[index], glsl::vec2(xL(node.first, maxLength), + yL(node.second)))); } - pixelSize = m2::PointU(my::rounds(maxLength), my::rounds(summaryHeight)); + pixelSize = m2::PointF(maxLength, summaryHeight); } } // namespace @@ -411,9 +357,11 @@ void StraightTextLayout::Cache(glm::vec4 const & pivot, glm::vec2 const & pixelO size_t beginOffset = 0; for (pair const & node : m_offsets) { - size_t endOffset = node.first; - StraigthTextOutlinedGeometryGenerator generator(pivot, pixelOffset + node.second, m_textSizeRatio, - colorRegion, outlineRegion, staticBuffer, dynamicBuffer); + StraightTextGeometryGenerator generator( + pivot, pixelOffset + node.second, m_textSizeRatio, dynamicBuffer, + colorRegion, outlineRegion, staticBuffer); + + size_t const endOffset = node.first; for (size_t index = beginOffset; index < endOffset && index < m_metrics.size(); ++index) generator(m_metrics[index]); @@ -429,9 +377,11 @@ void StraightTextLayout::Cache(glm::vec4 const & pivot, glm::vec2 const & pixelO size_t beginOffset = 0; for (pair const & node : m_offsets) { - size_t endOffset = node.first; - StraigthTextGeometryGenerator generator(pivot, pixelOffset + node.second, m_textSizeRatio, - color, staticBuffer, dynamicBuffer); + StraightTextGeometryGenerator generator( + pivot, pixelOffset + node.second, m_textSizeRatio, dynamicBuffer, + color, staticBuffer); + + size_t const endOffset = node.first; for (size_t index = beginOffset; index < endOffset && index < m_metrics.size(); ++index) generator(m_metrics[index]); @@ -490,7 +440,7 @@ bool PathTextLayout::CacheDynamicGeometry(m2::Spline::iterator const & iter, flo for (size_t i = 0; i < m_metrics.size(); ++i) { GlyphRegion const & g = m_metrics[i]; - m2::PointF pxSize = m2::PointF(g.GetPixelSize()) * m_textSizeRatio; + m2::PointF pxSize = g.GetPixelSize() * m_textSizeRatio; m2::PointD const pxBase = penIter.m_pos; m2::PointD const pxShiftBase = penIter.m_pos + penIter.m_dir; @@ -572,7 +522,6 @@ void PathTextLayout::CalculatePositions(vector & offsets, float splineLen } } -/////////////////////////////////////////////////////////////// SharedTextLayout::SharedTextLayout(PathTextLayout * layout) : m_layout(layout) { diff --git a/drape_frontend/text_layout.hpp b/drape_frontend/text_layout.hpp index 4d6ec971de..96545a1233 100644 --- a/drape_frontend/text_layout.hpp +++ b/drape_frontend/text_layout.hpp @@ -74,11 +74,11 @@ public: gpu::TTextStaticVertexBuffer & staticBuffer, gpu::TTextDynamicVertexBuffer & dynamicBuffer) const; - m2::PointU const & GetPixelSize() const { return m_pixelSize; } + m2::PointF const & GetPixelSize() const { return m_pixelSize; } private: buffer_vector, 2> m_offsets; - m2::PointU m_pixelSize; + m2::PointF m_pixelSize; }; class PathTextLayout : public TextLayout diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp index 05d5476aa8..01d10f5182 100644 --- a/drape_frontend/text_shape.cpp +++ b/drape_frontend/text_shape.cpp @@ -25,7 +25,7 @@ class StraightTextHandle : public TextHandle using TBase = TextHandle; public: - StraightTextHandle(FeatureID const & id, strings::UniString const & text, + StraightTextHandle(dp::OverlayID const & id, strings::UniString const & text, dp::Anchor anchor, glsl::vec2 const & pivot, glsl::vec2 const & pxSize, glsl::vec2 const & offset, uint64_t priority, int fixedHeight, @@ -123,11 +123,13 @@ private: } // namespace -TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params, bool hasPOI, - size_t textIndex, bool affectedByZoomPriority, int displacementMode, - uint16_t specialModePriority) +TextShape::TextShape(m2::PointD const & basePoint, TextViewParams const & params, + TileKey const & tileKey, bool hasPOI, + uint32_t textIndex, bool affectedByZoomPriority, + int displacementMode, uint16_t specialModePriority) : m_basePoint(basePoint) , m_params(params) + , m_tileCoords(tileKey.GetTileCoords()) , m_hasPOI(hasPOI) , m_affectedByZoomPriority(affectedByZoomPriority) , m_textIndex(textIndex) @@ -141,6 +143,14 @@ void TextShape::Draw(ref_ptr batcher, ref_ptr t StraightTextLayout primaryLayout(strings::MakeUniString(m_params.m_primaryText), m_params.m_primaryTextFont.m_size, m_params.m_primaryTextFont.m_isSdf, textures, m_params.m_anchor); + + if (m_params.m_limitedText && primaryLayout.GetPixelSize().y >= m_params.m_limits.y) + { + float const newFontSize = m_params.m_primaryTextFont.m_size * m_params.m_limits.y / primaryLayout.GetPixelSize().y; + primaryLayout = StraightTextLayout(strings::MakeUniString(m_params.m_primaryText), newFontSize, + m_params.m_primaryTextFont.m_isSdf, textures, m_params.m_anchor); + } + glsl::vec2 primaryOffset = glsl::ToVec2(m_params.m_primaryOffset); if (!m_params.m_secondaryText.empty()) @@ -149,7 +159,7 @@ void TextShape::Draw(ref_ptr batcher, ref_ptr t m_params.m_secondaryTextFont.m_size, m_params.m_secondaryTextFont.m_isSdf, textures, m_params.m_anchor); - glsl::vec2 secondaryOffset = primaryOffset; + glsl::vec2 secondaryOffset = primaryOffset + glsl::ToVec2(m_params.m_secondaryOffset); if (m_params.m_anchor & dp::Top) secondaryOffset += glsl::vec2(0.0, primaryLayout.GetPixelSize().y); @@ -217,9 +227,10 @@ void TextShape::DrawSubStringPlain(StraightTextLayout const & layout, dp::FontDe gpu::TTextDynamicVertexBuffer initialDynBuffer(dynamicBuffer.size()); - m2::PointU const & pixelSize = layout.GetPixelSize(); + m2::PointF const & pixelSize = layout.GetPixelSize(); - drape_ptr handle = make_unique_dp(m_params.m_featureID, + auto overlayId = dp::OverlayID(m_params.m_featureID, m_tileCoords, m_textIndex); + drape_ptr handle = make_unique_dp(overlayId, layout.GetText(), m_params.m_anchor, glsl::ToVec2(m_basePoint), @@ -266,9 +277,10 @@ void TextShape::DrawSubStringOutlined(StraightTextLayout const & layout, dp::Fon gpu::TTextDynamicVertexBuffer initialDynBuffer(dynamicBuffer.size()); - m2::PointU const & pixelSize = layout.GetPixelSize(); + m2::PointF const & pixelSize = layout.GetPixelSize(); - drape_ptr handle = make_unique_dp(m_params.m_featureID, + auto overlayId = dp::OverlayID(m_params.m_featureID, m_tileCoords, m_textIndex); + drape_ptr handle = make_unique_dp(overlayId, layout.GetText(), m_params.m_anchor, glsl::ToVec2(m_basePoint), diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp index c5198e1875..6e71fd3bb1 100644 --- a/drape_frontend/text_shape.hpp +++ b/drape_frontend/text_shape.hpp @@ -16,8 +16,9 @@ class StraightTextLayout; class TextShape : public MapShape { public: - TextShape(m2::PointF const & basePoint, TextViewParams const & params, bool hasPOI, - size_t textIndex, bool affectedByZoomPriority, + TextShape(m2::PointD const & basePoint, TextViewParams const & params, + TileKey const & tileKey, bool hasPOI, + uint32_t textIndex, bool affectedByZoomPriority, int displacementMode = dp::displacement::kAllModes, uint16_t specialModePriority = 0xFFFF); @@ -41,11 +42,12 @@ private: uint64_t GetOverlayPriority() const; - m2::PointF m_basePoint; + m2::PointD m_basePoint; TextViewParams m_params; + m2::PointI m_tileCoords; bool m_hasPOI; bool m_affectedByZoomPriority; - size_t m_textIndex; + uint32_t m_textIndex; bool m_disableDisplacing = false; int m_displacementMode; diff --git a/drape_frontend/tile_key.cpp b/drape_frontend/tile_key.cpp index 2449960f15..890c4df9f2 100755 --- a/drape_frontend/tile_key.cpp +++ b/drape_frontend/tile_key.cpp @@ -82,6 +82,11 @@ m2::RectD TileKey::GetGlobalRect(bool clipByDataMaxZoom) const return m2::RectD (startX, startY, startX + rectSize, startY + rectSize); } +m2::PointI TileKey::GetTileCoords() const +{ + return m2::PointI(m_x, m_y); +} + math::Matrix TileKey::GetTileBasedModelView(ScreenBase const & screen) const { return screen.GetModelView(GetGlobalRect().Center(), kShapeCoordScalar); diff --git a/drape_frontend/tile_key.hpp b/drape_frontend/tile_key.hpp index 9818728d4e..cc78284ed2 100755 --- a/drape_frontend/tile_key.hpp +++ b/drape_frontend/tile_key.hpp @@ -29,6 +29,8 @@ struct TileKey math::Matrix GetTileBasedModelView(ScreenBase const & screen) const; + m2::PointI GetTileCoords() const; + int m_x; int m_y; int m_zoomLevel; diff --git a/drape_frontend/visual_params.cpp b/drape_frontend/visual_params.cpp index 79eb0a35cb..f953568af9 100644 --- a/drape_frontend/visual_params.cpp +++ b/drape_frontend/visual_params.cpp @@ -93,7 +93,7 @@ string const & VisualParams::GetResourcePostfix(double visualScale) // Looking for the nearest available scale. int postfixIndex = -1; double minValue = numeric_limits::max(); - for (int i = 0; i < ARRAY_SIZE(postfixes); i++) + for (int i = 0; i < static_cast(ARRAY_SIZE(postfixes)); i++) { double val = fabs(postfixes[i].second - visualScale); if (val < minValue) diff --git a/drape_frontend/watch/cpu_drawer.cpp b/drape_frontend/watch/cpu_drawer.cpp index 24820b40eb..f8eadd038b 100644 --- a/drape_frontend/watch/cpu_drawer.cpp +++ b/drape_frontend/watch/cpu_drawer.cpp @@ -335,42 +335,6 @@ void CPUDrawer::DrawSymbol(m2::PointD const & pt, dp::Anchor pos, DrawRule const overlay.m_rects.push_back(rect); } -void CPUDrawer::DrawCircle(m2::PointD const & pt, dp::Anchor pos, DrawRule const & rule) -{ - m_pointShapes.emplace_back(pt, pos, TYPE_CIRCLE, rule, GetGeneration()); - OverlayWrapper & overlay = AddOverlay(&m_pointShapes.back()); - - CircleInfo info; - ConvertStyle(overlay.m_rules[0]->m_drawRule.m_rule->GetCircle(), m_visualScale, info); - - m2::RectD rect; - m_renderer->CalculateCircleMetric(pt, pos, info, rect); - overlay.m_rects.push_back(rect); -} - -void CPUDrawer::DrawCircledSymbol(m2::PointD const & pt, dp::Anchor pos, - DrawRule const & symbolRule, DrawRule const & circleRule) -{ - m_pointShapes.emplace_back(pt, pos, TYPE_CIRCLE, circleRule, GetGeneration()); - BaseShape const * circleShape = &m_pointShapes.back(); - m_pointShapes.emplace_back(pt, pos, TYPE_SYMBOL, symbolRule, GetGeneration()); - BaseShape const * symbolShape = &m_pointShapes.back(); - - OverlayWrapper & overlay = AddOverlay(circleShape, symbolShape); - - m2::RectD rect; - - CircleInfo circleInfo; - ConvertStyle(overlay.m_rules[0]->m_drawRule.m_rule->GetCircle(), m_visualScale, circleInfo); - m_renderer->CalculateCircleMetric(pt, pos, circleInfo, rect); - overlay.m_rects.push_back(rect); - - IconInfo symbolInfo; - ConvertStyle(overlay.m_rules[1]->m_drawRule.m_rule->GetSymbol(), symbolInfo); - m_renderer->CalculateSymbolMetric(pt, pos, symbolInfo, rect); - overlay.m_rects.back().Add(rect); -} - void CPUDrawer::DrawPath(PathInfo const & path, DrawRule const * rules, size_t count) { FeatureID const & id = Insert(path); @@ -525,9 +489,6 @@ void CPUDrawer::Render() case TYPE_SYMBOL: DrawSymbol(static_cast(shape)); break; - case TYPE_CIRCLE: - DrawCircle(static_cast(shape)); - break; case TYPE_PATH: DrawPath(static_cast(shape)); break; @@ -579,17 +540,6 @@ void CPUDrawer::DrawSymbol(PointShape const * shape) m_renderer->DrawSymbol(shape->m_position, shape->m_anchor, info); } -void CPUDrawer::DrawCircle(PointShape const * shape) -{ - ASSERT(shape->m_type == TYPE_CIRCLE, ()); - ASSERT(shape->m_drawRule.m_rule != nullptr, ()); - ASSERT(shape->m_drawRule.m_rule->GetCircle() != nullptr, ()); - - CircleInfo info; - ConvertStyle(shape->m_drawRule.m_rule->GetCircle(), m_visualScale, info); - m_renderer->DrawCircle(shape->m_position, shape->m_anchor, info); -} - void CPUDrawer::DrawPath(ComplexShape const * shape) { ASSERT(shape->m_type == TYPE_PATH, ()); @@ -762,9 +712,6 @@ void CPUDrawer::Draw(FeatureData const & data) bool const isArea = !data.m_areas.empty(); bool isCircleAndSymbol = false; - drule::BaseRule const * pCircleRule = nullptr; - double circleDepth = df::watch::minDepth; - drule::BaseRule const * pSymbolRule = nullptr; double symbolDepth = df::watch::minDepth; @@ -778,7 +725,6 @@ void CPUDrawer::Draw(FeatureData const & data) bool const isSymbol = pRule->GetSymbol() != 0; bool const isCaption = pRule->GetCaption(0) != 0; - bool const isCircle = pRule->GetCircle() != 0; if (pSymbolRule == nullptr && isSymbol) { @@ -786,12 +732,6 @@ void CPUDrawer::Draw(FeatureData const & data) symbolDepth = rules[i].m_depth; } - if (pCircleRule == nullptr && isCircle) - { - pCircleRule = pRule; - circleDepth = rules[i].m_depth; - } - if (pShieldRule == nullptr && pRule->GetShield() != nullptr) { pShieldRule = pRule; @@ -802,8 +742,6 @@ void CPUDrawer::Draw(FeatureData const & data) pathRules.push_back(rules[i]); } - isCircleAndSymbol = (pSymbolRule != nullptr) && (pCircleRule != nullptr); - if (!pathRules.empty()) { for (auto i = data.m_pathes.cbegin(); i != data.m_pathes.cend(); ++i) @@ -817,7 +755,6 @@ void CPUDrawer::Draw(FeatureData const & data) bool const isCaption = pRule->GetCaption(0) != 0; bool const isSymbol = pRule->GetSymbol() != 0; - bool const isCircle = pRule->GetCircle() != 0; if (!isCaption) { @@ -830,34 +767,15 @@ void CPUDrawer::Draw(FeatureData const & data) { if (isFill) DrawArea(*i, DrawRule(pRule, depth)); - else if (isCircleAndSymbol && isCircle) - { - DrawCircledSymbol(i->GetCenter(), - dp::Center, - DrawRule(pSymbolRule, symbolDepth), - DrawRule(pCircleRule, circleDepth)); - } else if (isSymbol) DrawSymbol(i->GetCenter(), dp::Center, DrawRule(pRule, depth)); - else if (isCircle) - DrawCircle(i->GetCenter(), dp::Center, DrawRule(pRule, depth)); } } // draw point symbol - if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0)) + if (isSymbol && !isPath && !isArea && ((pRule->GetType() & drule::node) != 0)) { - if (isCircleAndSymbol) - { - DrawCircledSymbol(data.m_point, - dp::Center, - DrawRule(pSymbolRule, symbolDepth), - DrawRule(pCircleRule, circleDepth)); - } - else if (isSymbol) - DrawSymbol(data.m_point, dp::Center, DrawRule(pRule, depth)); - else if (isCircle) - DrawCircle(data.m_point, dp::Center, DrawRule(pRule, depth)); + DrawSymbol(data.m_point, dp::Center, DrawRule(pRule, depth)); } } else diff --git a/drape_frontend/watch/cpu_drawer.hpp b/drape_frontend/watch/cpu_drawer.hpp index c5d39bb549..aa4e4b2b99 100644 --- a/drape_frontend/watch/cpu_drawer.hpp +++ b/drape_frontend/watch/cpu_drawer.hpp @@ -57,9 +57,6 @@ public: protected: void DrawSymbol(m2::PointD const & pt, dp::Anchor pos, DrawRule const & rule); - void DrawCircle(m2::PointD const & pt, dp::Anchor pos, DrawRule const & rule); - void DrawCircledSymbol(m2::PointD const & pt, dp::Anchor pos, - DrawRule const & symbolRule, DrawRule const & circleRule); void DrawPath(PathInfo const & path, DrawRule const * rules, size_t count); void DrawArea(AreaInfo const & area, DrawRule const & rule); void DrawText(m2::PointD const & pt, dp::Anchor pos, diff --git a/drape_frontend/watch/proto_to_styles.cpp b/drape_frontend/watch/proto_to_styles.cpp index 321986daa0..3b94ce6cc3 100644 --- a/drape_frontend/watch/proto_to_styles.cpp +++ b/drape_frontend/watch/proto_to_styles.cpp @@ -105,21 +105,6 @@ void ConvertStyle(SymbolRuleProto const * pSrc, IconInfo & dest) dest.m_name = pSrc->name(); } -void ConvertStyle(CircleRuleProto const * pSrc, double scale, CircleInfo & dest) -{ - dest = CircleInfo(pSrc->radius() * scale, ConvertColor(pSrc->color())); - - if (pSrc->has_border()) - { - PenInfo pen; - ConvertStyle(&(pSrc->border()), scale, pen); - - dest.m_isOutlined = true; - dest.m_outlineColor = pen.m_color; - dest.m_outlineWidth = pen.m_w; - } -} - void ConvertStyle(CaptionDefProto const * pSrc, double scale, dp::FontDecl & dest, m2::PointD & offset) { // fonts smaller than 8px look "jumpy" on LDPI devices diff --git a/drape_frontend/watch/proto_to_styles.hpp b/drape_frontend/watch/proto_to_styles.hpp index 4379f53b9b..feb75548fd 100644 --- a/drape_frontend/watch/proto_to_styles.hpp +++ b/drape_frontend/watch/proto_to_styles.hpp @@ -13,7 +13,6 @@ class LineDefProto; class AreaRuleProto; class SymbolRuleProto; class CaptionDefProto; -class CircleRuleProto; class ShieldRuleProto; namespace df @@ -26,7 +25,6 @@ dp::Color ConvertColor(uint32_t c); void ConvertStyle(LineDefProto const * pSrc, double scale, PenInfo & dest); void ConvertStyle(AreaRuleProto const * pSrc, BrushInfo & dest); void ConvertStyle(SymbolRuleProto const * pSrc, IconInfo & dest); -void ConvertStyle(CircleRuleProto const * pSrc, double scale, CircleInfo & dest); void ConvertStyle(CaptionDefProto const * pSrc, double scale, dp::FontDecl & dest, m2::PointD & offset); void ConvertStyle(ShieldRuleProto const * pSrc, double scale, dp::FontDecl & dest); diff --git a/drape_head/testing_engine.cpp b/drape_head/testing_engine.cpp index 0ff65a8cc7..04915eab35 100644 --- a/drape_head/testing_engine.cpp +++ b/drape_head/testing_engine.cpp @@ -12,7 +12,6 @@ #include "drape_frontend/path_symbol_shape.hpp" #include "drape_frontend/route_shape.hpp" #include "drape_frontend/area_shape.hpp" -#include "drape_frontend/circle_shape.hpp" #include "drape_frontend/poi_symbol_shape.hpp" #include "drape/utils/vertex_decl.hpp" @@ -55,7 +54,7 @@ public: for (gui::StaticLabel::Vertex & v : result.m_buffer) v.m_position = glsl::vec3(glsl::ToVec2(m_base), v.m_position.z); - dp::AttributeProvider provider(1 /* streamCount */, result.m_buffer.size()); + dp::AttributeProvider provider(1 /* streamCount */, static_cast(result.m_buffer.size())); provider.InitStream(0 /* streamIndex */, gui::StaticLabel::Vertex::GetBindingInfo(), make_ref(result.m_buffer.data())); @@ -98,7 +97,7 @@ public: textCacher.SetText(dynResult, m_text); ASSERT_EQUAL(staticData.m_buffer.size(), dynResult.m_buffer.size(), ()); - dp::AttributeProvider provider(2, dynResult.m_buffer.size()); + dp::AttributeProvider provider(2, static_cast(dynResult.m_buffer.size())); provider.InitStream(0 /* streamIndex */, gui::MutableLabel::StaticVertex::GetBindingInfo(), make_ref(staticData.m_buffer.data())); provider.InitStream(1 /* streamIndex */, gui::MutableLabel::DynamicVertex::GetBindingInfo(), @@ -442,7 +441,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, 0, true); + TextShape sh1(m2::PointF(82.277071f, 46.9271164f), params, TileKey(), false, 0, true); sh1.Draw(make_ref(m_batcher), make_ref(m_textures)); vector path; @@ -459,7 +458,7 @@ void TestingEngine::DrawImpl() ptvp.m_text = "Some text"; ptvp.m_textFont = dp::FontDecl(dp::Color::Black(), 40, true, dp::Color::Red()); - PathTextShape(spline, ptvp).Draw(make_ref(m_batcher), make_ref(m_textures)); + PathTextShape(spline, ptvp, TileKey(), 0).Draw(make_ref(m_batcher), make_ref(m_textures)); LineViewParams lvp; lvp.m_baseGtoPScale = ptvp.m_baseGtoPScale; lvp.m_depth = 90.0f; diff --git a/geometry/spline.cpp b/geometry/spline.cpp index 6c1ea569d5..0394b196be 100644 --- a/geometry/spline.cpp +++ b/geometry/spline.cpp @@ -15,9 +15,9 @@ Spline::Spline(vector const & path) m_direction = vector(cnt); m_length = vector(cnt); - for(int i = 0; i < cnt; ++i) + for(size_t i = 0; i < cnt; ++i) { - m_direction[i] = path[i+1] - path[i]; + m_direction[i] = path[i + 1] - path[i]; m_length[i] = m_direction[i].Length(); m_direction[i] = m_direction[i].Normalize(); } diff --git a/indexer/drawing_rules.cpp b/indexer/drawing_rules.cpp index 774743528a..2a8d66dd9e 100644 --- a/indexer/drawing_rules.cpp +++ b/indexer/drawing_rules.cpp @@ -95,11 +95,6 @@ text_type_t BaseRule::GetCaptionTextType(int) const return text_type_name; } -CircleRuleProto const * BaseRule::GetCircle() const -{ - return 0; -} - ShieldRuleProto const * BaseRule::GetShield() const { return nullptr; @@ -295,15 +290,6 @@ namespace typedef CaptionT Caption; typedef CaptionT PathText; - class Circle : public BaseRule - { - CircleRuleProto m_circle; - public: - Circle(CircleRuleProto const & r) : m_circle(r) {} - - virtual CircleRuleProto const * GetCircle() const { return &m_circle; } - }; - class Shield : public BaseRule { ShieldRuleProto m_shield; @@ -444,9 +430,6 @@ namespace if (de.has_caption()) AddRule(p, de.scale(), caption, de.caption(), apply_if); - if (de.has_circle()) - AddRule(p, de.scale(), circle, de.circle(), apply_if); - if (de.has_path_text()) AddRule(p, de.scale(), pathtext, de.path_text(), apply_if); diff --git a/indexer/drawing_rules.hpp b/indexer/drawing_rules.hpp index 6870cb869e..317e971ed5 100644 --- a/indexer/drawing_rules.hpp +++ b/indexer/drawing_rules.hpp @@ -19,7 +19,6 @@ class LineDefProto; class AreaRuleProto; class SymbolRuleProto; class CaptionDefProto; -class CircleRuleProto; class ShieldRuleProto; class ContainerProto; class FeatureType; @@ -56,7 +55,6 @@ namespace drule virtual SymbolRuleProto const * GetSymbol() const; virtual CaptionDefProto const * GetCaption(int) const; virtual text_type_t GetCaptionTextType(int) const; - virtual CircleRuleProto const * GetCircle() const; virtual ShieldRuleProto const * GetShield() const; // Test feature by runtime feature style selector diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index ec939f1880..c327d50fae 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -4,9 +4,11 @@ #include "indexer/feature_data.hpp" #include "indexer/classificator.hpp" -#include "std/map.hpp" -#include "std/sstream.hpp" -#include "std/utility.hpp" +#include +#include +#include +#include +#include namespace { @@ -543,4 +545,187 @@ bool IsTypeConformed(uint32_t type, StringIL const & path) } return true; } + +class RoadShieldParser +{ +public: + RoadShieldParser(std::string const & baseRoadNumber) + : m_baseRoadNumber(baseRoadNumber) + {} + virtual ~RoadShieldParser(){} + virtual RoadShield ParseRoadShield(std::string const & rawText) = 0; + + std::vector GetRoadShields() + { + std::vector result; + std::vector shieldsRawTests = strings::Tokenize(m_baseRoadNumber, ";"); + for (std::string const & rawText : shieldsRawTests) + { + RoadShield shield = ParseRoadShield(rawText); + if (!shield.m_name.empty()) + result.push_back(std::move(shield)); + } + return result; + } + +protected: + std::string const m_baseRoadNumber; +}; + +uint32_t constexpr kMaxRoadShieldTextSize = 8; + +class USRoadShieldParser : public RoadShieldParser +{ +public: + USRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + static std::vector kStatesCode = { + "US", "SR", "FSR", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", + "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", + "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", + "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AS", "GU", + "MP", "PR", "VI", "UM", "FM", "MH", "PW", + }; + + static std::vector kModifiers = { + "alt", "alternate", "bus", "business", "bypass", "historic", "connector", "loop", + "scenic", "spur", "temporary", "toll", "truck" + }; + + std::string shieldText = rawText; + + std::replace(shieldText.begin(), shieldText.end(), '-', ' '); + auto const shieldParts = strings::Tokenize(shieldText, " "); + + // Process long road shield titles to skip invalid data. + if (shieldText.size() > kMaxRoadShieldTextSize) + { + std::string lowerShieldText = shieldText; + strings::AsciiToLower(lowerShieldText); + + bool modifierFound = false; + for (auto const & modifier : kModifiers) + { + if (lowerShieldText.find(modifier) != std::string::npos) + { + modifierFound = true; + break; + } + } + if (!modifierFound) + return RoadShield(); + } + + if (shieldParts.size() <= 1) + { + return RoadShield(RoadShieldType::Default, rawText); + } + else + { + std::string const & roadType = shieldParts[0]; // 'I' for interstates and kStatesCode for highways. + std::string roadNumber = shieldParts[1]; + std::string additionalInfo; + if (shieldParts.size() >= 3) + { + additionalInfo = shieldParts[2]; + // Process cases like "US Loop 16". + if (!strings::is_number(shieldParts[1]) && strings::is_number(shieldParts[2])) + { + roadNumber = shieldParts[2]; + additionalInfo = shieldParts[1]; + } + } + if (roadType == "I") + return RoadShield(RoadShieldType::US_Interstate, roadNumber, additionalInfo); + else if (std::find(kStatesCode.begin(), kStatesCode.end(), shieldParts[0]) !=kStatesCode.end()) + return RoadShield(RoadShieldType::US_Highway, roadNumber, additionalInfo); + + return RoadShield(RoadShieldType::Default, rawText); + } + } +}; + +class SimpleRoadShieldParser : public RoadShieldParser +{ +public: + using ShieldTypes = std::unordered_map; + + SimpleRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) + : RoadShieldParser(baseRoadNumber) + , m_types(types) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldTextSize) + return RoadShield(); + + for (auto const & p : m_types) + { + if (rawText.find(p.first) != std::string::npos) + return RoadShield(p.second, rawText); + } + + return RoadShield(RoadShieldType::Default, rawText); + } + +private: + ShieldTypes const m_types; +}; + +class UKRoadShieldParser : public SimpleRoadShieldParser +{ +public: + UKRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'M', RoadShieldType::UK_Motorway}, + {'A', RoadShieldType::UK_Highway}}) + {} +}; + +class RussiaRoadShieldParser : public RoadShieldParser +{ +public: + RussiaRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldTextSize) + return RoadShield(); + + strings::UniString s = strings::MakeUniString(rawText); + if (s[0] == 'E' || s[0] == strings::UniChar(1045)) // Latin and cyrillic. + return RoadShield(RoadShieldType::Russia_Motorway, rawText); + + return RoadShield(RoadShieldType::Russia_Highway, rawText); + } +}; + +std::vector GetRoadShields(FeatureType const & f) +{ + std::string const roadNumber = f.GetRoadNumber(); + if (roadNumber.empty()) + return std::vector(); + + // Find out country name. + std::string mwmName = f.GetID().GetMwmName(); + ASSERT_NOT_EQUAL(mwmName, FeatureID::kInvalidFileName, ()); + auto const underlinePos = mwmName.find('_'); + if (underlinePos != std::string::npos) + mwmName = mwmName.substr(0, underlinePos); + + if (mwmName == "US") + return USRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "UK") + return UKRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Russia") + return RussiaRoadShieldParser(roadNumber).GetRoadShields(); + + return std::vector{RoadShield(RoadShieldType::Default, roadNumber)}; +} } // namespace ftypes diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index c3d6e02d5d..a63267e7be 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -240,4 +240,33 @@ enum class HighwayClass string DebugPrint(HighwayClass const cls); HighwayClass GetHighwayClass(feature::TypesHolder const & types); + +enum class RoadShieldType +{ + Default = 0, + US_Interstate, + US_Highway, + UK_Motorway, + UK_Highway, + Russia_Motorway, + Russia_Highway, + Count +}; + +struct RoadShield +{ + RoadShieldType m_type; + std::string m_name; + std::string m_additionalText; + + RoadShield() = default; + RoadShield(RoadShieldType const & type, std::string const & name) + : m_type(type), m_name(name) + {} + RoadShield(RoadShieldType const & type, std::string const & name, std::string const & additionalText) + : m_type(type), m_name(name), m_additionalText(additionalText) + {} +}; + +std::vector GetRoadShields(FeatureType const & f); } // namespace ftypes diff --git a/map/framework.cpp b/map/framework.cpp index 1cce5b23d4..e900626362 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1725,7 +1725,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, if (m_connectToGpsTrack) GpsTracker::Instance().Connect(bind(&Framework::OnUpdateGpsTrackPointsCallback, this, _1, _2)); - m_drapeEngine->RequestSymbolsSize(kSearchMarks, [this](vector const & sizes) + m_drapeEngine->RequestSymbolsSize(kSearchMarks, [this](vector const & sizes) { GetPlatform().RunOnGuiThread([this, sizes](){ m_searchMarksSizes = sizes; }); }); @@ -2827,7 +2827,7 @@ m2::PointD Framework::GetSearchMarkSize(SearchMarkType searchMarkType) return m2::PointD(); ASSERT_LESS(static_cast(searchMarkType), m_searchMarksSizes.size(), ()); - m2::PointU const pixelSize = m_searchMarksSizes[searchMarkType]; + m2::PointF const pixelSize = m_searchMarksSizes[searchMarkType]; double const pixelToMercator = m_currentModelView.GetScale(); return m2::PointD(pixelToMercator * pixelSize.x, pixelToMercator * pixelSize.y); diff --git a/map/framework.hpp b/map/framework.hpp index 687896699c..4fc943a39f 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -403,7 +403,7 @@ private: /// Here we store last selected feature to get its polygons in case of adding organization. mutable FeatureID m_selectedFeature; - vector m_searchMarksSizes; + vector m_searchMarksSizes; private: vector GetSelectedFeatureTriangles() const; diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj index 52f0853a43..06d4746cf9 100644 --- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj +++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ 452C9EE31CEDCF3200A55E57 /* scale_animation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 452C9ED11CEDCF3200A55E57 /* scale_animation.hpp */; }; 452C9EE41CEDCF3200A55E57 /* sequence_animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 452C9ED21CEDCF3200A55E57 /* sequence_animation.cpp */; }; 452C9EE51CEDCF3200A55E57 /* sequence_animation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 452C9ED31CEDCF3200A55E57 /* sequence_animation.hpp */; }; + 453EEA6D1E3A28F400505E09 /* colored_symbol_shape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 453EEA6B1E3A28F400505E09 /* colored_symbol_shape.cpp */; }; + 453EEA6E1E3A28F400505E09 /* colored_symbol_shape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 453EEA6C1E3A28F400505E09 /* colored_symbol_shape.hpp */; }; 454C19BB1CCE3EC0002A2C86 /* animation_constants.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */; }; 454C19BC1CCE3EC0002A2C86 /* animation_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */; }; 454C19BD1CCE3EC0002A2C86 /* animation_system.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */; }; @@ -128,7 +130,6 @@ 670947FB1BDF9BF5005014C0 /* backend_renderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670947ED1BDF9BF5005014C0 /* backend_renderer.hpp */; }; 670947FD1BDF9BF5005014C0 /* base_renderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670947EF1BDF9BF5005014C0 /* base_renderer.hpp */; }; 670947FF1BDF9BF5005014C0 /* batchers_pool.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670947F11BDF9BF5005014C0 /* batchers_pool.hpp */; }; - 670948011BDF9BF5005014C0 /* circle_shape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670947F31BDF9BF5005014C0 /* circle_shape.hpp */; }; 670948021BDF9BF5005014C0 /* drape_engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947F41BDF9BF5005014C0 /* drape_engine.cpp */; }; 670948031BDF9BF5005014C0 /* drape_engine.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670947F51BDF9BF5005014C0 /* drape_engine.hpp */; }; 670948141BDF9C39005014C0 /* base_interpolator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670948071BDF9C39005014C0 /* base_interpolator.cpp */; }; @@ -203,7 +204,6 @@ 67E91C761BDFC85E005CEE88 /* glyph_cache_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670948601BDF9C7F005014C0 /* glyph_cache_impl.cpp */; }; 67E91C781BDFC85E005CEE88 /* area_shape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947EA1BDF9BF5005014C0 /* area_shape.cpp */; }; 67E91C791BDFC85E005CEE88 /* base_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947EE1BDF9BF5005014C0 /* base_renderer.cpp */; }; - 67E91C7A1BDFC85E005CEE88 /* circle_shape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947F21BDF9BF5005014C0 /* circle_shape.cpp */; }; 67E91C7B1BDFC85E005CEE88 /* my_position_controller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947541BDF9BE0005014C0 /* my_position_controller.cpp */; }; 67E91C7C1BDFC85E005CEE88 /* selection_shape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947701BDF9BE0005014C0 /* selection_shape.cpp */; }; 67E91C7D1BDFC85E005CEE88 /* user_marks_provider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6709478B1BDF9BE0005014C0 /* user_marks_provider.cpp */; }; @@ -249,6 +249,8 @@ 452C9ED11CEDCF3200A55E57 /* scale_animation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scale_animation.hpp; sourceTree = ""; }; 452C9ED21CEDCF3200A55E57 /* sequence_animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sequence_animation.cpp; sourceTree = ""; }; 452C9ED31CEDCF3200A55E57 /* sequence_animation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = sequence_animation.hpp; sourceTree = ""; }; + 453EEA6B1E3A28F400505E09 /* colored_symbol_shape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colored_symbol_shape.cpp; sourceTree = ""; }; + 453EEA6C1E3A28F400505E09 /* colored_symbol_shape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = colored_symbol_shape.hpp; sourceTree = ""; }; 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_constants.hpp; sourceTree = ""; }; 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animation_system.cpp; sourceTree = ""; }; 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_system.hpp; sourceTree = ""; }; @@ -349,8 +351,6 @@ 670947EE1BDF9BF5005014C0 /* base_renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_renderer.cpp; sourceTree = ""; }; 670947EF1BDF9BF5005014C0 /* base_renderer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = base_renderer.hpp; sourceTree = ""; }; 670947F11BDF9BF5005014C0 /* batchers_pool.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = batchers_pool.hpp; sourceTree = ""; }; - 670947F21BDF9BF5005014C0 /* circle_shape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = circle_shape.cpp; sourceTree = ""; }; - 670947F31BDF9BF5005014C0 /* circle_shape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = circle_shape.hpp; sourceTree = ""; }; 670947F41BDF9BF5005014C0 /* drape_engine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drape_engine.cpp; sourceTree = ""; }; 670947F51BDF9BF5005014C0 /* drape_engine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_engine.hpp; sourceTree = ""; }; 670948071BDF9C39005014C0 /* base_interpolator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_interpolator.cpp; sourceTree = ""; }; @@ -466,6 +466,8 @@ 670947411BDF9B99005014C0 /* drape_frontend */ = { isa = PBXGroup; children = ( + 453EEA6B1E3A28F400505E09 /* colored_symbol_shape.cpp */, + 453EEA6C1E3A28F400505E09 /* colored_symbol_shape.hpp */, 347F52071DC2334A0064B273 /* drape_api_builder.cpp */, 347F52081DC2334A0064B273 /* drape_api_builder.hpp */, 347F52091DC2334A0064B273 /* drape_api_renderer.cpp */, @@ -520,8 +522,6 @@ 670947EE1BDF9BF5005014C0 /* base_renderer.cpp */, 670947EF1BDF9BF5005014C0 /* base_renderer.hpp */, 670947F11BDF9BF5005014C0 /* batchers_pool.hpp */, - 670947F21BDF9BF5005014C0 /* circle_shape.cpp */, - 670947F31BDF9BF5005014C0 /* circle_shape.hpp */, 670947F41BDF9BF5005014C0 /* drape_engine.cpp */, 670947F51BDF9BF5005014C0 /* drape_engine.hpp */, 670947E01BDF9BEC005014C0 /* engine_context.cpp */, @@ -722,7 +722,6 @@ 670948701BDF9C7F005014C0 /* feature_processor.hpp in Headers */, 452C9EDF1CEDCF3200A55E57 /* parallel_animation.hpp in Headers */, 670947A41BDF9BE1005014C0 /* my_position_controller.hpp in Headers */, - 670948011BDF9BF5005014C0 /* circle_shape.hpp in Headers */, 452C9ED91CEDCF3200A55E57 /* follow_animation.hpp in Headers */, 670947A01BDF9BE1005014C0 /* message_queue.hpp in Headers */, 452C9ED51CEDCF3200A55E57 /* animation.hpp in Headers */, @@ -795,6 +794,7 @@ 670947B01BDF9BE1005014C0 /* read_manager.hpp in Headers */, 670947CF1BDF9BE1005014C0 /* tile_key.hpp in Headers */, 670947BA1BDF9BE1005014C0 /* route_renderer.hpp in Headers */, + 453EEA6E1E3A28F400505E09 /* colored_symbol_shape.hpp in Headers */, 670948201BDF9C39005014C0 /* value_mapping.hpp in Headers */, 670948441BDF9C48005014C0 /* drape_gui.hpp in Headers */, 670947DD1BDF9BE1005014C0 /* viewport.hpp in Headers */, @@ -888,7 +888,6 @@ 67E91C761BDFC85E005CEE88 /* glyph_cache_impl.cpp in Sources */, 67E91C781BDFC85E005CEE88 /* area_shape.cpp in Sources */, 67E91C791BDFC85E005CEE88 /* base_renderer.cpp in Sources */, - 67E91C7A1BDFC85E005CEE88 /* circle_shape.cpp in Sources */, 452C9ED61CEDCF3200A55E57 /* arrow_animation.cpp in Sources */, 67E91C7B1BDFC85E005CEE88 /* my_position_controller.cpp in Sources */, 454C19BC1CCE3EC0002A2C86 /* animation_system.cpp in Sources */, @@ -909,6 +908,7 @@ 670947BB1BDF9BE1005014C0 /* route_shape.cpp in Sources */, 6709479D1BDF9BE1005014C0 /* message_acceptor.cpp in Sources */, 6709483B1BDF9C48005014C0 /* compass.cpp in Sources */, + 453EEA6D1E3A28F400505E09 /* colored_symbol_shape.cpp in Sources */, 670947921BDF9BE1005014C0 /* kinetic_scroller.cpp in Sources */, 6709484D1BDF9C48005014C0 /* shape.cpp in Sources */, 675D218C1BFB871D00717E4F /* proto_to_styles.cpp in Sources */,