diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index a72e62562b..98dc2929aa 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -604,6 +604,7 @@ void ApplyPointFeature::Finish(ref_ptr texMng) textParams.m_specialPriority = specialModePriority; textParams.m_startOverlayRank = hasPOI ? dp::OverlayRank1 : dp::OverlayRank0; m_insertShape(make_unique_dp(m_centerPoint, textParams, m_tileKey, symbolSize, + m2::PointF(0.0f, 0.0f) /* symbolOffset */, dp::Center /* symbolAnchor */, 0 /* textIndex */)); } } @@ -1190,6 +1191,7 @@ void ApplyLineFeatureAdditional::Finish(ref_ptr texMng, m_insertShape(make_unique_dp(shieldPos, textParams, m_tileKey, m2::PointF(0.0f, 0.0f) /* symbolSize */, + m2::PointF(0.0f, 0.0f) /* symbolOffset */, dp::Center /* symbolAnchor */, textIndex)); if (IsColoredRoadShield(shield)) m_insertShape(make_unique_dp(shieldPos, symbolParams, m_tileKey, textIndex)); diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 0388493d8e..81ca0a183e 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -249,6 +249,7 @@ void DrapeEngine::UpdateUserMarksGroup(MarkGroupID groupId, UserMarksProvider * renderInfo->m_symbolNames = mark->GetSymbolNames(); renderInfo->m_coloredSymbols = mark->GetColoredSymbols(); renderInfo->m_symbolSizes = mark->GetSymbolSizes(); + renderInfo->m_symbolOffsets = mark->GetSymbolOffsets(); renderInfo->m_hasSymbolPriority = mark->HasSymbolPriority(); renderInfo->m_hasTitlePriority = mark->HasTitlePriority(); renderInfo->m_priority = mark->GetPriority(); diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index eb1dea1dd3..d85396a90f 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -555,9 +555,10 @@ void RuleDrawer::DrawTileNet(TInsertShapeFn const & insertShape) strings::to_string(key.m_zoomLevel); tp.m_titleDecl.m_primaryTextFont = dp::FontDecl(dp::Color::Red(), 30); - tp.m_titleDecl.m_primaryOffset = {0.f, 0.f}; + tp.m_titleDecl.m_primaryOffset = {0.0f, 0.0f}; drape_ptr textShape = make_unique_dp(r.Center(), tp, key, - m2::PointF(0.0, 0.0) /* symbolSize */, + m2::PointF(0.0f, 0.0f) /* symbolSize */, + m2::PointF(0.0f, 0.0f) /* symbolOffset */, dp::Anchor::Center, 0 /* textIndex */); textShape->DisableDisplacing(); diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp index f64b9bd1c5..906c617189 100644 --- a/drape_frontend/text_shape.cpp +++ b/drape_frontend/text_shape.cpp @@ -151,12 +151,13 @@ private: TextShape::TextShape(m2::PointD const & basePoint, TextViewParams const & params, TileKey const & tileKey, - m2::PointF const & symbolSize, dp::Anchor symbolAnchor, + m2::PointF const & symbolSize, m2::PointF const & symbolOffset, dp::Anchor symbolAnchor, uint32_t textIndex) : m_basePoint(basePoint) , m_params(params) , m_tileCoords(tileKey.GetTileCoords()) , m_symbolAnchor(symbolAnchor) + , m_symbolOffset(symbolOffset) , m_textIndex(textIndex) { m_symbolSizes.push_back(symbolSize); @@ -164,12 +165,13 @@ TextShape::TextShape(m2::PointD const & basePoint, TextViewParams const & params TextShape::TextShape(m2::PointD const & basePoint, TextViewParams const & params, TileKey const & tileKey, std::vector const & symbolSizes, - dp::Anchor symbolAnchor, uint32_t textIndex) + m2::PointF const & symbolOffset, dp::Anchor symbolAnchor, uint32_t textIndex) : m_basePoint(basePoint) , m_params(params) , m_tileCoords(tileKey.GetTileCoords()) , m_symbolSizes(symbolSizes) , m_symbolAnchor(symbolAnchor) + , m_symbolOffset(symbolOffset) , m_textIndex(textIndex) { ASSERT_GREATER(m_symbolSizes.size(), 0, ()); @@ -260,6 +262,8 @@ void TextShape::Draw(ref_ptr batcher, ref_ptr t CalculateTextOffsets(titleDecl, primaryLayout.GetPixelSize(), secondaryLayout != nullptr ? secondaryLayout->GetPixelSize() : m2::PointF(0.0f, 0.0f), primaryOffset, secondaryOffset); + primaryOffset += glsl::vec2(m_symbolOffset.x, m_symbolOffset.y); + secondaryOffset += glsl::vec2(m_symbolOffset.x, m_symbolOffset.y); if (primaryLayout.GetGlyphCount() > 0) { diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp index f6244c9cab..47ae779137 100644 --- a/drape_frontend/text_shape.hpp +++ b/drape_frontend/text_shape.hpp @@ -18,12 +18,12 @@ class TextShape : public MapShape { public: TextShape(m2::PointD const & basePoint, TextViewParams const & params, - TileKey const & tileKey, m2::PointF const & symbolSize, + TileKey const & tileKey, m2::PointF const & symbolSize, m2::PointF const & symbolOffset, dp::Anchor symbolAnchor, uint32_t textIndex); TextShape(m2::PointD const & basePoint, TextViewParams const & params, TileKey const & tileKey, std::vector const & symbolSizes, - dp::Anchor symbolAnchor, uint32_t textIndex); + m2::PointF const & symbolOffset, dp::Anchor symbolAnchor, uint32_t textIndex); void Draw(ref_ptr batcher, ref_ptr textures) const override; MapShapeType GetType() const override { return MapShapeType::OverlayType; } @@ -50,6 +50,7 @@ private: m2::PointI m_tileCoords; std::vector m_symbolSizes; dp::Anchor m_symbolAnchor; + m2::PointF m_symbolOffset; uint32_t m_textIndex; bool m_disableDisplacing = false; diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp index ea232ddba3..f7bcd56165 100644 --- a/drape_frontend/user_mark_shapes.cpp +++ b/drape_frontend/user_mark_shapes.cpp @@ -15,6 +15,7 @@ #include "drape/batcher.hpp" #include "indexer/feature_decl.hpp" +#include "indexer/scales.hpp" #include "geometry/clipping.hpp" #include "geometry/mercator.hpp" @@ -119,7 +120,8 @@ void CacheUserMarks(TileKey const & tileKey, ref_ptr texture m2::PointD const tileCenter = tileKey.GetGlobalRect().Center(); depthLayer = renderInfo.m_depthLayer; - m2::PointF symbolSize; + m2::PointF symbolSize(0.0f, 0.0f); + m2::PointF symbolOffset(0.0f, 0.0f); std::string symbolName; if (renderInfo.m_symbolNames != nullptr) { @@ -178,7 +180,18 @@ void CacheUserMarks(TileKey const & tileKey, ref_ptr texture params.m_specialDisplacement = SpecialDisplacement::UserMark; params.m_specialPriority = renderInfo.m_priority; params.m_symbolName = symbolName; + params.m_anchor = renderInfo.m_anchor; params.m_startOverlayRank = renderInfo.m_coloredSymbols != nullptr ? dp::OverlayRank1 : dp::OverlayRank0; + if (renderInfo.m_symbolOffsets != nullptr) + { + ASSERT_GREATER(tileKey.m_zoomLevel, 0, ()); + ASSERT_LESS_OR_EQUAL(tileKey.m_zoomLevel, scales::UPPER_STYLE_SCALE, ()); + size_t offsetIndex = 0; + if (tileKey.m_zoomLevel > 0) + offsetIndex = static_cast(min(tileKey.m_zoomLevel - 1, scales::UPPER_STYLE_SCALE)); + symbolOffset = renderInfo.m_symbolOffsets->at(offsetIndex); + params.m_offset = symbolOffset; + } PoiSymbolShape(renderInfo.m_pivot, params, tileKey, kStartUserMarkOverlayIndex + renderInfo.m_index).Draw(&batcher, textures); } @@ -263,13 +276,14 @@ void CacheUserMarks(TileKey const & tileKey, ref_ptr texture if (renderInfo.m_symbolSizes != nullptr) { - TextShape(renderInfo.m_pivot, params, tileKey, - *renderInfo.m_symbolSizes.get(), renderInfo.m_anchor, overlayIndex).Draw(&batcher, textures); + TextShape(renderInfo.m_pivot, params, tileKey, *renderInfo.m_symbolSizes.get(), + m2::PointF(0.0f, 0.0f) /* symbolOffset */, renderInfo.m_anchor, + overlayIndex).Draw(&batcher, textures); } else { TextShape(renderInfo.m_pivot, params, tileKey, - symbolSize, renderInfo.m_anchor, overlayIndex).Draw(&batcher, textures); + symbolSize, symbolOffset, renderInfo.m_anchor, overlayIndex).Draw(&batcher, textures); } } } diff --git a/drape_frontend/user_mark_shapes.hpp b/drape_frontend/user_mark_shapes.hpp index 99ebc73e80..f649dc5400 100644 --- a/drape_frontend/user_mark_shapes.hpp +++ b/drape_frontend/user_mark_shapes.hpp @@ -24,6 +24,7 @@ struct UserMarkRenderParams drape_ptr m_symbolNames; drape_ptr m_titleDecl; drape_ptr m_symbolSizes; + drape_ptr m_symbolOffsets; bool m_hasSymbolPriority = false; bool m_hasTitlePriority = false; uint16_t m_priority = 0; diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp index a31329c260..3ee85681ca 100644 --- a/drape_frontend/user_marks_provider.hpp +++ b/drape_frontend/user_marks_provider.hpp @@ -43,6 +43,7 @@ public: using SymbolNameZoomInfo = std::map; using TitlesInfo = std::vector; using SymbolSizes = std::vector; + using SymbolOffsets = std::vector; UserPointMark(); virtual ~UserPointMark() {} @@ -62,6 +63,7 @@ public: virtual drape_ptr GetSymbolNames() const = 0; virtual drape_ptr GetColoredSymbols() const = 0; virtual drape_ptr GetSymbolSizes() const = 0; + virtual drape_ptr GetSymbolOffsets() const = 0; virtual uint16_t GetPriority() const = 0; virtual uint32_t GetIndex() const = 0; virtual bool HasSymbolPriority() const = 0; diff --git a/map/routing_mark.cpp b/map/routing_mark.cpp index 8a2180acea..0bea98f5fe 100644 --- a/map/routing_mark.cpp +++ b/map/routing_mark.cpp @@ -488,6 +488,28 @@ drape_ptr TransitMark::GetSymbolSizes() const return make_unique_dp(m_symbolSizes); } +void TransitMark::SetSymbolOffsets(SymbolOffsets const & symbolOffsets) +{ + m_symbolOffsets = symbolOffsets; +} + +drape_ptr TransitMark::GetSymbolOffsets() const +{ + if (m_symbolOffsets.empty()) + return nullptr; + return make_unique_dp(m_symbolOffsets); +} + +void TransitMark::SetAnchor(dp::Anchor anchor) +{ + m_anchor = anchor; +} + +dp::Anchor TransitMark::GetAnchor() const +{ + return m_anchor; +} + drape_ptr TransitMark::GetSymbolNames() const { if (m_symbolNames.empty()) diff --git a/map/routing_mark.hpp b/map/routing_mark.hpp index 0a1334746e..b69a85cfc8 100644 --- a/map/routing_mark.hpp +++ b/map/routing_mark.hpp @@ -110,13 +110,15 @@ public: TransitMark(m2::PointD const & ptOrg, UserMarkContainer * container); virtual ~TransitMark() {} - dp::Anchor GetAnchor() const override { return dp::Center; } df::RenderState::DepthLayer GetDepthLayer() const override { return df::RenderState::TransitMarkLayer; } UserMark::Type GetMarkType() const override { return Type::TRANSIT; } bool HasSymbolPriority() const override { return !m_symbolNames.empty() || !m_coloredSymbols.empty(); } bool HasTitlePriority() const override { return true; } + void SetAnchor(dp::Anchor anchor); + dp::Anchor GetAnchor() const override; + void SetFeatureId(FeatureID featureId); FeatureID GetFeatureID() const override { return m_featureId; } @@ -141,6 +143,9 @@ public: void SetSymbolSizes(SymbolSizes const & symbolSizes); drape_ptr GetSymbolSizes() const override; + void SetSymbolOffsets(SymbolOffsets const & symbolSizes); + drape_ptr GetSymbolOffsets() const override; + void AddTitle(dp::TitleDecl const & titleDecl); drape_ptr GetTitleDecl() const override; @@ -156,4 +161,6 @@ private: SymbolNameZoomInfo m_symbolNames; ColoredSymbolZoomInfo m_coloredSymbols; SymbolSizes m_symbolSizes; + SymbolOffsets m_symbolOffsets; + dp::Anchor m_anchor = dp::Center; }; diff --git a/map/transit/transit_display.cpp b/map/transit/transit_display.cpp index 4eaf5baea5..591b225f21 100644 --- a/map/transit/transit_display.cpp +++ b/map/transit/transit_display.cpp @@ -27,7 +27,7 @@ const int kLargeIconZoom = 15; const int kMinStopTitleZoom = 13; -const int kTransferTitleOffset = 1; +const int kTransferTitleOffset = 2; const int kStopTitleOffset = 0; const int kGateTitleOffset = 0; @@ -457,25 +457,37 @@ void TransitRouteDisplay::CollectTransitDisplayInfo(vector const & } } +TransitMark * TransitRouteDisplay::CreateMark(m2::PointD const & pt, FeatureID const & fid) +{ + auto & marksController = m_bmManager->GetUserMarksController(UserMark::Type::TRANSIT); + uint32_t const nextIndex = static_cast(marksController.GetUserMarkCount()); + + auto userMark = marksController.CreateUserMark(pt); + ASSERT(dynamic_cast(userMark) != nullptr, ()); + auto transitMark = static_cast(userMark); + + transitMark->SetFeatureId(fid); + transitMark->SetIndex(nextIndex); + return transitMark; +} + void TransitRouteDisplay::CreateTransitMarks(std::vector const & transitMarks) { std::vector const transferMarkerSizes = GetTransitMarkerSizes(kTransferMarkerScale, m_maxSubrouteWidth); std::vector const stopMarkerSizes = GetTransitMarkerSizes(kStopMarkerScale, m_maxSubrouteWidth); - auto & marksController = m_bmManager->GetUserMarksController(UserMark::Type::TRANSIT); - uint32_t nextIndex = static_cast(marksController.GetUserMarkCount()); + std::vector transferArrowOffsets; + for (auto const & size : transferMarkerSizes) + transferArrowOffsets.emplace_back(0.0f, size.y * 0.5f); + + auto const vs = static_cast(df::VisualParams::Instance().GetVisualScale()); for (size_t i = 0; i < transitMarks.size(); ++i) { auto const & mark = transitMarks[i]; + auto transitMark = CreateMark(mark.m_point, mark.m_featureId); - auto userMark = marksController.CreateUserMark(mark.m_point); - ASSERT(dynamic_cast(userMark) != nullptr, ()); - auto transitMark = static_cast(userMark); dp::TitleDecl titleDecl; - - transitMark->SetFeatureId(mark.m_featureId); - transitMark->SetIndex(nextIndex++); if (mark.m_type == TransitMarkInfo::Type::Gate) { if (!mark.m_titles.empty()) @@ -498,20 +510,27 @@ void TransitRouteDisplay::CreateTransitMarks(std::vector const { if (mark.m_titles.size() > 1) { + auto titleTransitMark = CreateMark(mark.m_point, mark.m_featureId); + TransitMark::GetDefaultTransitTitle(titleDecl); titleDecl.m_primaryText = mark.m_titles.front().m_text; titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.front().m_color); - titleDecl.m_primaryOffset.y = -kTransferTitleOffset; - titleDecl.m_anchor = dp::Anchor::Bottom; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); + titleDecl.m_primaryOffset.x = -kTransferTitleOffset * vs; + titleDecl.m_anchor = dp::Anchor::Right; + titleDecl.m_primaryOptional = false; + titleTransitMark->AddTitle(titleDecl); titleDecl.m_primaryText = mark.m_titles.back().m_text; titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.back().m_color); - titleDecl.m_primaryOffset.y = kTransferTitleOffset; - titleDecl.m_anchor = dp::Anchor::Top; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); + titleDecl.m_primaryOffset.x = kTransferTitleOffset * vs; + titleDecl.m_anchor = dp::Anchor::Left; + titleDecl.m_primaryOptional = false; + titleTransitMark->AddTitle(titleDecl); + + titleTransitMark->SetAnchor(dp::Top); + titleTransitMark->SetSymbolNames({{1 /* minZoom */, "transfer_arrow"}}); + titleTransitMark->SetSymbolOffsets(transferArrowOffsets); + titleTransitMark->SetPriority(UserMark::Priority::TransitTransfer); } df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; for (size_t sizeIndex = 0; sizeIndex < transferMarkerSizes.size(); ++sizeIndex) @@ -524,7 +543,6 @@ void TransitRouteDisplay::CreateTransitMarks(std::vector const if (coloredSymbol.empty() || coloredSymbol.rbegin()->second.m_radiusInPixels != params.m_radiusInPixels) coloredSymbol.insert(make_pair(zoomLevel, params)); } - transitMark->SetSymbolSizes(transferMarkerSizes); transitMark->SetColoredSymbols(coloredSymbol); transitMark->SetPriority(UserMark::Priority::TransitTransfer); } @@ -588,5 +606,6 @@ void TransitRouteDisplay::CreateTransitMarks(std::vector const } } + auto & marksController = m_bmManager->GetUserMarksController(UserMark::Type::TRANSIT); marksController.NotifyChanges(); } diff --git a/map/transit/transit_display.hpp b/map/transit/transit_display.hpp index 9e3a4963cb..03127d7a9b 100644 --- a/map/transit/transit_display.hpp +++ b/map/transit/transit_display.hpp @@ -116,6 +116,7 @@ private: void CollectTransitDisplayInfo(std::vector const & segments, TransitDisplayInfos & transitDisplayInfos); void CreateTransitMarks(std::vector const & transitMarks); + TransitMark * CreateMark(m2::PointD const & pt, FeatureID const & fid); TransitReadManager & m_transitReadManager; GetMwmIdFn m_getMwmIdFn; diff --git a/map/user_mark.hpp b/map/user_mark.hpp index f158a36279..13dcba4a01 100644 --- a/map/user_mark.hpp +++ b/map/user_mark.hpp @@ -58,6 +58,7 @@ public: drape_ptr GetTitleDecl() const override { return nullptr; } drape_ptr GetColoredSymbols() const override { return nullptr; } drape_ptr GetSymbolSizes() const override { return nullptr; } + drape_ptr GetSymbolOffsets() const override { return nullptr; } uint16_t GetPriority() const override { return static_cast(Priority::Default); } uint32_t GetIndex() const override { return 0; } bool HasSymbolPriority() const override { return false; }