diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index 4e34f3aad6..ce27fa4bbd 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -129,6 +129,8 @@ set( message_queue.cpp message_queue.hpp message_subclasses.hpp + metaline_manager.cpp + metaline_manager.hpp my_position.cpp my_position.hpp my_position_controller.cpp @@ -149,6 +151,8 @@ set( postprocess_renderer.hpp read_manager.cpp read_manager.hpp + read_metaline_task.cpp + read_metaline_task.hpp read_mwm_task.cpp read_mwm_task.hpp render_group.cpp diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index ee8af08d56..18bd89160d 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -728,23 +728,24 @@ void ApplyAreaFeature::ProcessRule(Stylist::TRuleWrapper const & rule) } } -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(tileKey.m_zoomLevel >= kLineSimplifyLevelStart && tileKey.m_zoomLevel <= kLineSimplifyLevelEnd) +ApplyLineFeatureGeometry::ApplyLineFeatureGeometry(TileKey const & tileKey, + TInsertShapeFn const & insertShape, + FeatureID const & id, + double currentScaleGtoP, + int minVisibleScale, uint8_t rank, + size_t pointsCount) + : TBase(tileKey, insertShape, id, minVisibleScale, rank, CaptionDescription()) + , m_currentScaleGtoP(static_cast(currentScaleGtoP)) + , m_sqrScale(math::sqr(currentScaleGtoP)) + , m_simplify(tileKey.m_zoomLevel >= kLineSimplifyLevelStart && + tileKey.m_zoomLevel <= kLineSimplifyLevelEnd) , m_initialPointsCount(pointsCount) - , m_shieldDepth(0.0) - , m_shieldRule(nullptr) #ifdef CALC_FILTERED_POINTS , m_readedCount(0) #endif -{ -} +{} -void ApplyLineFeature::operator() (m2::PointD const & point) +void ApplyLineFeatureGeometry::operator() (m2::PointD const & point) { #ifdef CALC_FILTERED_POINTS ++m_readedCount; @@ -775,96 +776,125 @@ void ApplyLineFeature::operator() (m2::PointD const & point) } } -bool ApplyLineFeature::HasGeometry() const +bool ApplyLineFeatureGeometry::HasGeometry() const { return m_spline->IsValid(); } -void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) +void ApplyLineFeatureGeometry::ProcessRule(Stylist::TRuleWrapper const & rule) { ASSERT(HasGeometry(), ()); drule::BaseRule const * pRule = rule.first; - float depth = rule.second; + float const depth = static_cast(rule.second); - bool isWay = (pRule->GetType() & drule::way) != 0; - CaptionDefProto const * pCaptionRule = pRule->GetCaption(0); LineDefProto const * pLineRule = pRule->GetLine(); - ShieldRuleProto const * pShieldRule = pRule->GetShield(); + if (pLineRule == nullptr) + return; m_clippedSplines = m2::ClipSplineByRect(m_tileRect, m_spline); - if (m_clippedSplines.empty()) return; - if (pCaptionRule != nullptr && pCaptionRule->height() > 2 && - !m_captions.GetPathName().empty() && isWay) + if (pLineRule->has_pathsym()) { - dp::FontDecl fontDecl; - CaptionDefProtoToFontDecl(pCaptionRule, fontDecl); - - PathTextViewParams params; + PathSymProto const & symRule = pLineRule->pathsym(); + PathSymbolViewParams params; params.m_tileCenter = m_tileRect.Center(); - params.m_featureID = m_id; params.m_depth = depth; params.m_minVisibleScale = m_minVisibleScale; params.m_rank = m_rank; - params.m_text = m_captions.GetPathName(); - params.m_textFont = fontDecl; + params.m_symbolName = symRule.name(); + double const mainScale = df::VisualParams::Instance().GetVisualScale(); + params.m_offset = static_cast(symRule.offset() * mainScale); + params.m_step = static_cast(symRule.step() * mainScale); params.m_baseGtoPScale = m_currentScaleGtoP; - uint32_t baseTextIndex = kPathTextBaseTextIndex; for (auto const & spline : m_clippedSplines) - { - m_insertShape(make_unique_dp(spline, params, m_tileKey, baseTextIndex)); - baseTextIndex += kPathTextBaseTextStep; - } + m_insertShape(make_unique_dp(spline, params)); } - - if (pLineRule != nullptr) + else { - if (pLineRule->has_pathsym()) - { - PathSymProto const & symRule = pLineRule->pathsym(); - PathSymbolViewParams params; - params.m_tileCenter = m_tileRect.Center(); - params.m_depth = depth; - params.m_minVisibleScale = m_minVisibleScale; - params.m_rank = m_rank; - params.m_symbolName = symRule.name(); - double const mainScale = df::VisualParams::Instance().GetVisualScale(); - params.m_offset = symRule.offset() * mainScale; - params.m_step = symRule.step() * mainScale; - params.m_baseGtoPScale = m_currentScaleGtoP; + LineViewParams params; + 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_tileKey.m_zoomLevel; - for (auto const & spline : m_clippedSplines) - m_insertShape(make_unique_dp(spline, params)); - } - else - { - LineViewParams params; - 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_tileKey.m_zoomLevel; - - for (auto const & spline : m_clippedSplines) - m_insertShape(make_unique_dp(spline, params)); - } + for (auto const & spline : m_clippedSplines) + m_insertShape(make_unique_dp(spline, params)); } +} +void ApplyLineFeatureGeometry::Finish() +{ +#ifdef CALC_FILTERED_POINTS + LinesStat::Get().InsertLine(m_id, m_currentScaleGtoP, m_readedCount, m_spline->GetSize()); +#endif +} + +ApplyLineFeatureAdditional::ApplyLineFeatureAdditional(TileKey const & tileKey, + TInsertShapeFn const & insertShape, + FeatureID const & id, + double currentScaleGtoP, + int minVisibleScale, uint8_t rank, + CaptionDescription const & captions, + std::vector const & clippedSplines) + : TBase(tileKey, insertShape, id, minVisibleScale, rank, captions) + , m_clippedSplines(clippedSplines) + , m_currentScaleGtoP(static_cast(currentScaleGtoP)) + , m_shieldDepth(0.0f) + , m_shieldRule(nullptr) +{} + +void ApplyLineFeatureAdditional::ProcessRule(Stylist::TRuleWrapper const & rule) +{ + if (m_clippedSplines.empty()) + return; + + drule::BaseRule const * pRule = rule.first; + float const depth = static_cast(rule.second); + ShieldRuleProto const * pShieldRule = pRule->GetShield(); if (pShieldRule != nullptr) { m_shieldDepth = depth; m_shieldRule = pShieldRule; } + + bool const isWay = (pRule->GetType() & drule::way) != 0; + if (!isWay) + return; + + CaptionDefProto const * pCaptionRule = pRule->GetCaption(0); + if (pCaptionRule == nullptr || pCaptionRule->height() <= 2 || m_captions.GetPathName().empty()) + return; + + dp::FontDecl fontDecl; + CaptionDefProtoToFontDecl(pCaptionRule, fontDecl); + PathTextViewParams params; + params.m_tileCenter = m_tileRect.Center(); + params.m_featureID = m_id; + params.m_depth = depth; + params.m_minVisibleScale = m_minVisibleScale; + params.m_rank = m_rank; + params.m_text = m_captions.GetPathName(); + 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_tileKey, baseTextIndex)); + baseTextIndex += kPathTextBaseTextStep; + } } -void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shield, TextViewParams & textParams, - ColoredSymbolViewParams & symbolParams, - PoiSymbolViewParams & poiParams) +void ApplyLineFeatureAdditional::GetRoadShieldsViewParams(ftypes::RoadShield const & shield, + TextViewParams & textParams, + ColoredSymbolViewParams & symbolParams, + PoiSymbolViewParams & poiParams) { ASSERT (m_shieldRule != nullptr, ()); @@ -877,7 +907,7 @@ void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shiel ShieldRuleProtoToFontDecl(m_shieldRule, baseFont); dp::FontDecl font = GetRoadShieldTextFont(baseFont, shield); textParams.m_tileCenter = m_tileRect.Center(); - textParams.m_depth = static_cast(m_shieldDepth); + textParams.m_depth = m_shieldDepth; textParams.m_minVisibleScale = m_minVisibleScale; textParams.m_rank = m_rank; textParams.m_anchor = dp::Center; @@ -900,7 +930,7 @@ void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shiel // Generated symbol properties. symbolParams.m_featureID = m_id; symbolParams.m_tileCenter = m_tileRect.Center(); - symbolParams.m_depth = static_cast(m_shieldDepth); + symbolParams.m_depth = m_shieldDepth; symbolParams.m_minVisibleScale = m_minVisibleScale; symbolParams.m_rank = m_rank; symbolParams.m_shape = ColoredSymbolViewParams::Shape::RoundedRectangle; @@ -933,7 +963,7 @@ void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shiel } poiParams.m_tileCenter = m_tileRect.Center(); - poiParams.m_depth = static_cast(m_shieldDepth); + poiParams.m_depth = m_shieldDepth; poiParams.m_minVisibleScale = m_minVisibleScale; poiParams.m_rank = m_rank; poiParams.m_symbolName = symbolName; @@ -945,12 +975,8 @@ void ApplyLineFeature::GetRoadShieldsViewParams(ftypes::RoadShield const & shiel } } -void ApplyLineFeature::Finish(ref_ptr texMng, std::set && roadShields) +void ApplyLineFeatureAdditional::Finish(std::set && roadShields) { -#ifdef CALC_FILTERED_POINTS - LinesStat::Get().InsertLine(m_id, m_currentScaleGtoP, m_readedCount, m_spline->GetSize()); -#endif - if (m_shieldRule == nullptr || m_clippedSplines.empty()) return; @@ -989,11 +1015,13 @@ void ApplyLineFeature::Finish(ref_ptr texMng, std::set(shieldOffset + it.m_pos, symbolParams, m_tileKey, textIndex)); + 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)); + m_insertShape(make_unique_dp(shieldOffset + it.m_pos, + poiParams, m_tileKey, textIndex)); } it.Advance(splineStep); textIndex++; @@ -1003,10 +1031,4 @@ void ApplyLineFeature::Finish(ref_ptr texMng, std::setGetPath()) : m2::PolylineD(); -} - -} // namespace df +} // namespace df diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index 58121cd73b..afc81863bc 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -144,21 +144,48 @@ private: double const m_currentScaleGtoP; }; -class ApplyLineFeature : public BaseApplyFeature +class ApplyLineFeatureGeometry : public BaseApplyFeature { using TBase = BaseApplyFeature; public: - ApplyLineFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, FeatureID const & id, - double currentScaleGtoP, int minVisibleScale, uint8_t rank, - CaptionDescription const & captions, size_t pointsCount); + ApplyLineFeatureGeometry(TileKey const & tileKey, TInsertShapeFn const & insertShape, + FeatureID const & id, double currentScaleGtoP, int minVisibleScale, + uint8_t rank, size_t pointsCount); void operator() (m2::PointD const & point); bool HasGeometry() const; void ProcessRule(Stylist::TRuleWrapper const & rule); - void Finish(ref_ptr texMng, std::set && roadShields); + void Finish(); - m2::PolylineD GetPolyline() const; + std::vector const & GetClippedSplines() const { return m_clippedSplines; } + +private: + m2::SharedSpline m_spline; + vector m_clippedSplines; + float m_currentScaleGtoP; + double m_sqrScale; + m2::PointD m_lastAddedPoint; + bool m_simplify; + size_t m_initialPointsCount; + +#ifdef CALC_FILTERED_POINTS + int m_readedCount; +#endif +}; + +class ApplyLineFeatureAdditional : public BaseApplyFeature +{ + using TBase = BaseApplyFeature; + +public: + ApplyLineFeatureAdditional(TileKey const & tileKey, TInsertShapeFn const & insertShape, + FeatureID const & id, double currentScaleGtoP, int minVisibleScale, + uint8_t rank, CaptionDescription const & captions, + std::vector const & clippedSplines); + + void ProcessRule(Stylist::TRuleWrapper const & rule); + void Finish(std::set && roadShields); private: void GetRoadShieldsViewParams(ftypes::RoadShield const & shield, @@ -166,19 +193,10 @@ private: ColoredSymbolViewParams & symbolParams, PoiSymbolViewParams & poiParams); - m2::SharedSpline m_spline; - vector m_clippedSplines; - double m_currentScaleGtoP; - double m_sqrScale; - m2::PointD m_lastAddedPoint; - bool m_simplify; - size_t m_initialPointsCount; - double m_shieldDepth; + std::vector m_clippedSplines; + float m_currentScaleGtoP; + float m_shieldDepth; ShieldRuleProto const * m_shieldRule; - -#ifdef CALC_FILTERED_POINTS - int m_readedCount; -#endif }; extern dp::Color ToDrapeColor(uint32_t src); diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index ad0065c1a8..5a4c365155 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -7,6 +7,7 @@ #include "drape_frontend/drape_measurer.hpp" #include "drape_frontend/map_shape.hpp" #include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/metaline_manager.hpp" #include "drape_frontend/read_manager.hpp" #include "drape_frontend/route_builder.hpp" #include "drape_frontend/user_mark_shapes.hpp" @@ -33,6 +34,7 @@ BackendRenderer::BackendRenderer(Params && params) , m_trafficGenerator(make_unique_dp(bind(&BackendRenderer::FlushTrafficRenderData, this, _1))) , m_requestedTiles(params.m_requestedTiles) , m_updateCurrentCountryFn(params.m_updateCurrentCountryFn) + , m_metalineManager(make_unique_dp(params.m_commutator, m_model)) { #ifdef DEBUG m_isTeardowned = false; @@ -111,7 +113,8 @@ void BackendRenderer::AcceptMessage(ref_ptr message) bool have3dBuildings; bool forceRequest; m_requestedTiles->GetParams(screen, have3dBuildings, forceRequest); - m_readManager->UpdateCoverage(screen, have3dBuildings, forceRequest, tiles, m_texMng); + m_readManager->UpdateCoverage(screen, have3dBuildings, forceRequest, tiles, m_texMng, + make_ref(m_metalineManager)); m_updateCurrentCountryFn(screen.ClipRect().Center(), (*tiles.begin()).m_zoomLevel); } break; @@ -468,6 +471,7 @@ void BackendRenderer::ReleaseResources() m_readManager->Stop(); m_readManager.reset(); + m_metalineManager.reset(); m_batchersPool.reset(); m_routeBuilder.reset(); m_overlays.clear(); diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 0c38709b11..fdedc42dc3 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -24,6 +24,7 @@ namespace df class Message; class ReadManager; class RouteBuilder; +class MetalineManager; class BackendRenderer : public BaseRenderer { @@ -111,6 +112,8 @@ private: TUpdateCurrentCountryFn m_updateCurrentCountryFn; + drape_ptr m_metalineManager; + #ifdef DEBUG bool m_isTeardowned; #endif diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index da8970357d..f2ba02e446 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -63,6 +63,7 @@ SOURCES += \ map_data_provider.cpp \ message_acceptor.cpp \ message_queue.cpp \ + metaline_manager.cpp \ my_position.cpp \ my_position_controller.cpp \ navigator.cpp \ @@ -73,6 +74,7 @@ SOURCES += \ poi_symbol_shape.cpp \ postprocess_renderer.cpp \ read_manager.cpp \ + read_metaline_task.cpp \ read_mwm_task.cpp \ render_group.cpp \ render_node.cpp \ @@ -172,6 +174,7 @@ HEADERS += \ message_acceptor.hpp \ message_queue.hpp \ message_subclasses.hpp \ + metaline_manager.hpp \ my_position.hpp \ my_position_controller.hpp \ navigator.hpp \ @@ -182,6 +185,7 @@ HEADERS += \ poi_symbol_shape.hpp \ postprocess_renderer.hpp \ read_manager.hpp \ + read_metaline_task.hpp \ read_mwm_task.hpp \ render_group.hpp \ render_node.hpp \ diff --git a/drape_frontend/engine_context.cpp b/drape_frontend/engine_context.cpp index 5d3237a3aa..2c2419e1b2 100644 --- a/drape_frontend/engine_context.cpp +++ b/drape_frontend/engine_context.cpp @@ -11,6 +11,7 @@ namespace df EngineContext::EngineContext(TileKey tileKey, ref_ptr commutator, ref_ptr texMng, + ref_ptr metalineMng, CustomSymbolsContextWeakPtr customSymbolsContext, bool is3dBuildingsEnabled, bool isTrafficEnabled, @@ -18,6 +19,7 @@ EngineContext::EngineContext(TileKey tileKey, : m_tileKey(tileKey) , m_commutator(commutator) , m_texMng(texMng) + , m_metalineMng(metalineMng) , m_customSymbolsContext(customSymbolsContext) , m_3dBuildingsEnabled(is3dBuildingsEnabled) , m_trafficEnabled(isTrafficEnabled) @@ -29,6 +31,11 @@ ref_ptr EngineContext::GetTextureManager() const return m_texMng; } +ref_ptr EngineContext::GetMetalineManager() const +{ + return m_metalineMng; +} + void EngineContext::BeginReadTile() { PostMessage(make_unique_dp(m_tileKey)); @@ -61,5 +68,4 @@ void EngineContext::PostMessage(drape_ptr && message) m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(message), MessagePriority::Normal); } - -} // namespace df +} // namespace df diff --git a/drape_frontend/engine_context.hpp b/drape_frontend/engine_context.hpp index 262d936e9a..948b78d6a1 100644 --- a/drape_frontend/engine_context.hpp +++ b/drape_frontend/engine_context.hpp @@ -12,11 +12,12 @@ namespace dp { class TextureManager; -} // namespace dp +} // namespace dp namespace df { class Message; +class MetalineManager; class EngineContext { @@ -24,6 +25,7 @@ public: EngineContext(TileKey tileKey, ref_ptr commutator, ref_ptr texMng, + ref_ptr metalineMng, CustomSymbolsContextWeakPtr customSymbolsContext, bool is3dBuildingsEnabled, bool isTrafficEnabled, @@ -35,6 +37,7 @@ public: int GetDisplacementMode() const { return m_displacementMode; } CustomSymbolsContextWeakPtr GetCustomSymbolsContext() const { return m_customSymbolsContext; } ref_ptr GetTextureManager() const; + ref_ptr GetMetalineManager() const; void BeginReadTile(); void Flush(TMapShapes && shapes); @@ -48,6 +51,7 @@ private: TileKey m_tileKey; ref_ptr m_commutator; ref_ptr m_texMng; + ref_ptr m_metalineMng; CustomSymbolsContextWeakPtr m_customSymbolsContext; bool m_3dBuildingsEnabled; bool m_trafficEnabled; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 0b61336380..487d063eb6 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -768,6 +768,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::RegenerateTraffic: case Message::SetSimplifiedTrafficColors: case Message::SetDisplacementMode: + case Message::UpdateMetalines: { m_forceUpdateScene = true; break; diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 25e7159014..9a7459fef6 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -82,6 +82,7 @@ public: SetPostprocessStaticTextures, SetPosteffectEnabled, RunFirstLaunchAnimation, + UpdateMetalines, }; virtual ~Message() {} diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index c2cb3aba99..f09a4b2c8d 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -1260,4 +1260,10 @@ class RunFirstLaunchAnimationMessage : public Message public: Type GetType() const override { return Message::RunFirstLaunchAnimation; } }; + +class UpdateMetalinesMessage : public Message +{ +public: + Type GetType() const override { return Message::UpdateMetalines; } +}; } // namespace df diff --git a/drape_frontend/metaline_manager.cpp b/drape_frontend/metaline_manager.cpp new file mode 100644 index 0000000000..4d3c1b9e57 --- /dev/null +++ b/drape_frontend/metaline_manager.cpp @@ -0,0 +1,76 @@ +#include "drape_frontend/metaline_manager.hpp" + +#include "drape_frontend/map_data_provider.hpp" +#include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/threads_commutator.hpp" + +#include "base/logging.hpp" + +#include + +namespace df +{ +MetalineManager::MetalineManager(ref_ptr commutator, MapDataProvider & model) + : m_model(model) + , m_tasksPool(4, ReadMetalineTaskFactory(m_model)) + , m_threadsPool(make_unique_dp(2, std::bind(&MetalineManager::OnTaskFinished, + this, std::placeholders::_1))) + , m_commutator(commutator) +{} + +MetalineManager::~MetalineManager() +{ + m_threadsPool->Stop(); + m_threadsPool.reset(); +} + +void MetalineManager::Update(std::set const & mwms) +{ + std::lock_guard lock(m_mwmsMutex); + for (auto const & mwm : mwms) + { + auto const result = m_mwms.insert(mwm); + if (result.second) + { + ReadMetalineTask * task = m_tasksPool.Get(); + task->Init(mwm); + m_threadsPool->PushBack(task); + } + } +} + +m2::SharedSpline MetalineManager::GetMetaline(FeatureID const & fid) const +{ + std::lock_guard lock(m_metalineCacheMutex); + auto const metalineIt = m_metalineCache.find(fid); + if (metalineIt == m_metalineCache.end()) + return m2::SharedSpline(); + return metalineIt->second; +} + +void MetalineManager::OnTaskFinished(threads::IRoutine * task) +{ + ASSERT(dynamic_cast(task) != nullptr, ()); + ReadMetalineTask * t = static_cast(task); + + // Update metaline cache. + if (!task->IsCancelled()) + { + std::lock_guard lock(m_metalineCacheMutex); + auto const & metalines = t->GetMetalines(); + for (auto const & metaline : metalines) + m_metalineCache[metaline.first] = metaline.second; + + if (!metalines.empty()) + { + LOG(LDEBUG, ("Metalines prepared:", t->GetMwmId())); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(), + MessagePriority::Normal); + } + } + + t->Reset(); + m_tasksPool.Return(t); +} +} // namespace df diff --git a/drape_frontend/metaline_manager.hpp b/drape_frontend/metaline_manager.hpp new file mode 100644 index 0000000000..152d2c23c2 --- /dev/null +++ b/drape_frontend/metaline_manager.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "drape_frontend/read_metaline_task.hpp" + +#include "drape/object_pool.hpp" +#include "drape/pointers.hpp" + +#include "indexer/feature_decl.hpp" + +#include +#include + +namespace df +{ +class ThreadsCommutator; + +class MetalineManager +{ +public: + MetalineManager(ref_ptr commutator, MapDataProvider & model); + ~MetalineManager(); + + void Update(std::set const & mwms); + + m2::SharedSpline GetMetaline(FeatureID const & fid) const; + +private: + void OnTaskFinished(threads::IRoutine * task); + + using TasksPool = ObjectPool; + + MapDataProvider & m_model; + + MetalineCache m_metalineCache; + mutable std::mutex m_metalineCacheMutex; + + std::set m_mwms; + std::mutex m_mwmsMutex; + + TasksPool m_tasksPool; + drape_ptr m_threadsPool; + ref_ptr m_commutator; +}; +} // namespace df diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index aaedb8c6f0..81864e4263 100755 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -1,5 +1,6 @@ #include "drape_frontend/read_manager.hpp" #include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/metaline_manager.hpp" #include "drape_frontend/visual_params.hpp" #include "drape/constants.hpp" @@ -96,7 +97,8 @@ void ReadManager::OnTaskFinished(threads::IRoutine * task) void ReadManager::UpdateCoverage(ScreenBase const & screen, bool have3dBuildings, bool forceUpdate, TTilesCollection const & tiles, - ref_ptr texMng) + ref_ptr texMng, + ref_ptr metalineMng) { m_modeChanged |= (m_have3dBuildings != have3dBuildings); m_have3dBuildings = have3dBuildings; @@ -113,7 +115,7 @@ void ReadManager::UpdateCoverage(ScreenBase const & screen, m_generationCounter++; for (auto const & tileKey : tiles) - PushTaskBackForTileKey(tileKey, texMng); + PushTaskBackForTileKey(tileKey, texMng, metalineMng); } else { @@ -141,7 +143,7 @@ void ReadManager::UpdateCoverage(ScreenBase const & screen, IncreaseCounter(static_cast(newTiles.size())); CheckFinishedTiles(readyTiles); for (auto const & tileKey : newTiles) - PushTaskBackForTileKey(tileKey, texMng); + PushTaskBackForTileKey(tileKey, texMng, metalineMng); } m_currentViewport = screen; @@ -200,10 +202,13 @@ bool ReadManager::MustDropAllTiles(ScreenBase const & screen) const return (oldScale != newScale) || !m_currentViewport.GlobalRect().IsIntersect(screen.GlobalRect()); } -void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr texMng) +void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, + ref_ptr texMng, + ref_ptr metalineMng) { auto context = make_unique_dp(TileKey(tileKey, m_generationCounter), - m_commutator, texMng, m_customSymbolsContext, + m_commutator, texMng, metalineMng, + m_customSymbolsContext, m_have3dBuildings && m_allow3dBuildings, m_trafficEnabled, m_displacementMode); std::shared_ptr tileInfo = std::make_shared(std::move(context)); diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index df58e43f8f..373b9c1d22 100755 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -10,7 +10,6 @@ #include "drape/object_pool.hpp" #include "drape/pointers.hpp" -#include "drape/texture_manager.hpp" #include "base/thread_pool.hpp" @@ -19,10 +18,16 @@ #include #include +namespace dp +{ +class TextureManager; +} // namespace dp + namespace df { class MapDataProvider; class CoverageUpdateDescriptor; +class MetalineManager; uint8_t constexpr kReadingThreadsCount = 2; @@ -33,7 +38,8 @@ public: bool allow3dBuildings, bool trafficEnabled); void UpdateCoverage(ScreenBase const & screen, bool have3dBuildings, bool forceUpdate, - TTilesCollection const & tiles, ref_ptr texMng); + TTilesCollection const & tiles, ref_ptr texMng, + ref_ptr metalineMng); void Invalidate(TTilesCollection const & keyStorage); void InvalidateAll(); void Stop(); @@ -55,7 +61,8 @@ private: void OnTaskFinished(threads::IRoutine * task); bool MustDropAllTiles(ScreenBase const & screen) const; - void PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr texMng); + void PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr texMng, + ref_ptr metalineMng); ref_ptr m_commutator; diff --git a/drape_frontend/read_metaline_task.cpp b/drape_frontend/read_metaline_task.cpp new file mode 100644 index 0000000000..1aa403d732 --- /dev/null +++ b/drape_frontend/read_metaline_task.cpp @@ -0,0 +1,171 @@ +#include "drape_frontend/read_metaline_task.hpp" + +#include "drape_frontend/drape_api.hpp" +#include "drape_frontend/map_data_provider.hpp" +#include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/metaline_manager.hpp" +#include "drape_frontend/threads_commutator.hpp" + +#include "coding/file_container.hpp" +#include "coding/reader_wrapper.hpp" +#include "coding/varint.hpp" + +#include "indexer/feature_decl.hpp" +#include "indexer/scales.hpp" + +#include "defines.hpp" + +#include +#include + +namespace +{ +double const kPointEqualityEps = 1e-7; + +struct MetalineData +{ + std::vector m_features; + std::vector m_directions; +}; + +std::vector ReadMetalinesFromFile(MwmSet::MwmId const & mwmId) +{ + try + { + std::vector model; + ModelReaderPtr reader = FilesContainerR(mwmId.GetInfo()->GetLocalFile().GetPath(MapOptions::Map)) + .GetReader(METALINES_FILE_TAG); + ReaderSrc src(reader.GetPtr()); + uint8_t const version = ReadPrimitiveFromSource(src); + if (version == 1) + { + for (auto metalineIndex = ReadVarUint(src); metalineIndex > 0; --metalineIndex) + { + MetalineData data; + for (auto i = ReadVarUint(src); i > 0; --i) + { + int32_t const fid = ReadVarInt(src); + data.m_features.push_back(FeatureID(mwmId, static_cast(std::abs(fid)))); + data.m_directions.push_back(fid > 0); + } + model.push_back(std::move(data)); + } + } + return model; + } + catch (Reader::Exception const &) + { + return {}; + } +} + +std::vector MergePoints(std::vector> const & points) +{ + size_t sz = 0; + for (auto const & p : points) + sz += p.size(); + + std::vector result; + result.reserve(sz); + for (size_t i = 0; i < points.size(); i++) + { + for (auto const & pt : points[i]) + { + if (result.empty() || !result.back().EqualDxDy(pt, kPointEqualityEps)) + result.push_back(pt); + } + } + return result; +} +} // namespace + +namespace df +{ +ReadMetalineTask::ReadMetalineTask(MapDataProvider & model) + : m_model(model) +{} + +void ReadMetalineTask::Init(MwmSet::MwmId const & mwmId) +{ + m_mwmId = mwmId; +} + +void ReadMetalineTask::Reset() +{ + m_mwmId.Reset(); +} + +bool ReadMetalineTask::IsCancelled() const +{ + return IRoutine::IsCancelled(); +} + +void ReadMetalineTask::Do() +{ + if (!m_mwmId.IsAlive()) + return; + + auto metalines = ReadMetalinesFromFile(m_mwmId); + for (auto const & metaline : metalines) + { + bool failed = false; + for (auto const & fid : metaline.m_features) + { + if (m_metalines.find(fid) != m_metalines.end()) + { + failed = true; + break; + } + } + if (failed) + continue; + + size_t curIndex = 0; + std::vector> points; + points.reserve(5); + m_model.ReadFeatures([&metaline, &failed, &curIndex, &points](FeatureType const & ft) + { + if (failed) + return; + if (ft.GetID() != metaline.m_features[curIndex]) + { + failed = true; + return; + } + std::vector featurePoints; + featurePoints.reserve(5); + ft.ForEachPoint([&featurePoints](m2::PointD const & pt) + { + if (!featurePoints.back().EqualDxDy(pt, kPointEqualityEps)) + featurePoints.push_back(pt); + }, scales::GetUpperScale()); + if (featurePoints.size() < 2) + { + failed = true; + return; + } + if (!metaline.m_directions[curIndex]) + std::reverse(featurePoints.begin(), featurePoints.end()); + + points.push_back(std::move(featurePoints)); + curIndex++; + }, metaline.m_features); + + if (failed || points.empty()) + continue; + + std::vector const mergedPoints = MergePoints(points); + if (mergedPoints.empty()) + continue; + + m2::SharedSpline const spline(mergedPoints); + for (auto const & fid : metaline.m_features) + m_metalines[fid] = spline; + } +} + +ReadMetalineTask * ReadMetalineTaskFactory::GetNew() const +{ + return new ReadMetalineTask(m_model); +} +} // namespace df diff --git a/drape_frontend/read_metaline_task.hpp b/drape_frontend/read_metaline_task.hpp new file mode 100644 index 0000000000..5c57f38f44 --- /dev/null +++ b/drape_frontend/read_metaline_task.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "drape/pointers.hpp" + +#include "indexer/feature_decl.hpp" + +#include "geometry/spline.hpp" + +#include "base/thread.hpp" +#include "base/thread_pool.hpp" + +#include + +namespace df +{ +class MapDataProvider; + +using MetalineCache = std::map; + +class ReadMetalineTask : public threads::IRoutine +{ +public: + ReadMetalineTask(MapDataProvider & model); + + void Init(MwmSet::MwmId const & mwmId); + + void Do() override; + void Reset() override; + bool IsCancelled() const override; + + MetalineCache const & GetMetalines() const { return m_metalines; } + MwmSet::MwmId const & GetMwmId() const { return m_mwmId; } + +private: + MapDataProvider & m_model; + MwmSet::MwmId m_mwmId; + MetalineCache m_metalines; +}; + +class ReadMetalineTaskFactory +{ +public: + ReadMetalineTaskFactory(MapDataProvider & model) + : m_model(model) + {} + + ReadMetalineTask * GetNew() const; + +private: + MapDataProvider & m_model; +}; +} // namespace df diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 00d75b79a4..904178a162 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -15,6 +15,8 @@ #include "indexer/road_shields_parser.hpp" #include "indexer/scales.hpp" +#include "geometry/clipping.hpp" + #include "base/assert.hpp" #include "base/logging.hpp" @@ -317,23 +319,55 @@ void RuleDrawer::ProcessAreaStyle(FeatureType const & f, Stylist const & s, TIns apply.Finish(m_context->GetTextureManager(), m_customSymbolsContext); } -void RuleDrawer::ProcessLineStyle(FeatureType const & f, Stylist const & s, TInsertShapeFn const & insertShape, +void RuleDrawer::ProcessLineStyle(FeatureType const & f, Stylist const & s, + TInsertShapeFn const & insertShape, int & minVisibleScale) { int const zoomLevel = m_context->GetTileKey().m_zoomLevel; - ApplyLineFeature apply(m_context->GetTileKey(), insertShape, f.GetID(), - m_currentScaleGtoP, minVisibleScale, f.GetRank(), - s.GetCaptionDescription(), f.GetPointsCount()); - f.ForEachPoint(apply, zoomLevel); + ApplyLineFeatureGeometry applyGeom(m_context->GetTileKey(), insertShape, f.GetID(), + m_currentScaleGtoP, minVisibleScale, f.GetRank(), + f.GetPointsCount()); + f.ForEachPoint(applyGeom, zoomLevel); if (CheckCancelled()) return; - if (apply.HasGeometry()) - s.ForEachRule(bind(&ApplyLineFeature::ProcessRule, &apply, _1)); + if (applyGeom.HasGeometry()) + s.ForEachRule(bind(&ApplyLineFeatureGeometry::ProcessRule, &applyGeom, _1)); + applyGeom.Finish(); - apply.Finish(m_context->GetTextureManager(), ftypes::GetRoadShields(f)); + std::vector clippedSplines; + bool needAdditional; + auto const metalineSpline = m_context->GetMetalineManager()->GetMetaline(f.GetID()); + if (metalineSpline.IsNull()) + { + // There is no metaline for this feature. + needAdditional = true; + clippedSplines = applyGeom.GetClippedSplines(); + } + else if (m_usedMetalines.find(metalineSpline.Get()) != m_usedMetalines.end()) + { + // Metaline has been used already, skip additional generation. + needAdditional = false; + } + else + { + // Generate additional by metaline, mark metaline spline as used. + needAdditional = true; + clippedSplines = m2::ClipSplineByRect(m_context->GetTileKey().GetGlobalRect(), + metalineSpline); + m_usedMetalines.insert(metalineSpline.Get()); + } + + if (needAdditional && !clippedSplines.empty()) + { + ApplyLineFeatureAdditional applyAdditional(m_context->GetTileKey(), insertShape, f.GetID(), + m_currentScaleGtoP, minVisibleScale, f.GetRank(), + s.GetCaptionDescription(), clippedSplines); + s.ForEachRule(bind(&ApplyLineFeatureAdditional::ProcessRule, &applyAdditional, _1)); + applyAdditional.Finish(ftypes::GetRoadShields(f)); + } if (m_context->IsTrafficEnabled() && zoomLevel >= kRoadClass0ZoomLevel) { @@ -498,9 +532,8 @@ void RuleDrawer::DrawTileNet(TInsertShapeFn const & insertShape) strings::to_string(key.m_zoomLevel); tp.m_primaryTextFont = dp::FontDecl(dp::Color::Red(), 30); - tp.m_primaryOffset = {0.0f, 0.0f}; - drape_ptr textShape = - make_unique_dp(r.Center(), tp, m_context->GetTileKey(), false, 0, false); + tp.m_primaryOffset = {0.f, 0.f}; + drape_ptr textShape = make_unique_dp(r.Center(), tp, key, false, 0, false); textShape->DisableDisplacing(); insertShape(std::move(textShape)); } diff --git a/drape_frontend/rule_drawer.hpp b/drape_frontend/rule_drawer.hpp index d3dd90a93c..ee3bd6148f 100644 --- a/drape_frontend/rule_drawer.hpp +++ b/drape_frontend/rule_drawer.hpp @@ -2,6 +2,7 @@ #include "drape_frontend/custom_symbol.hpp" #include "drape_frontend/map_shape.hpp" +#include "drape_frontend/metaline_manager.hpp" #include "drape_frontend/tile_key.hpp" #include "drape_frontend/traffic_generator.hpp" @@ -13,6 +14,7 @@ #include #include #include +#include class FeatureType; @@ -59,6 +61,8 @@ private: ref_ptr m_context; CustomSymbolsContextPtr m_customSymbolsContext; + std::unordered_set m_usedMetalines; + m2::RectD m_globalRect; double m_currentScaleGtoP; double m_trafficScalePtoG; diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index c027318507..3db6ba026f 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -2,6 +2,7 @@ #include "drape_frontend/drape_measurer.hpp" #include "drape_frontend/engine_context.hpp" #include "drape_frontend/map_data_provider.hpp" +#include "drape_frontend/metaline_manager.hpp" #include "drape_frontend/rule_drawer.hpp" #include "drape_frontend/stylist.hpp" @@ -13,7 +14,6 @@ #include "base/logging.hpp" #include -#include namespace df { @@ -29,30 +29,25 @@ m2::RectD TileInfo::GetGlobalRect() const void TileInfo::ReadFeatureIndex(MapDataProvider const & model) { - if (DoNeedReadIndex()) + if (!DoNeedReadIndex()) + return; + + CheckCanceled(); + + size_t const kAverageFeaturesCount = 256; + m_featureInfo.reserve(kAverageFeaturesCount); + + MwmSet::MwmId lastMwm; + model.ReadFeaturesID([this, &lastMwm](FeatureID const & id) { - CheckCanceled(); - - size_t const kAverageFeaturesCount = 256; - m_featureInfo.reserve(kAverageFeaturesCount); - -#ifdef DEBUG - std::set existing; - MwmSet::MwmId lastMwm; - model.ReadFeaturesID([this, &existing, &lastMwm](FeatureID const & id) + if (m_mwms.empty() || lastMwm != id.m_mwmId) { - if (existing.empty() || lastMwm != id.m_mwmId) - { - ASSERT(existing.insert(id.m_mwmId).second, ()); - lastMwm = id.m_mwmId; - } -#else - model.ReadFeaturesID([this](FeatureID const & id) - { -#endif - m_featureInfo.push_back(id); - }, GetGlobalRect(), GetZoomLevel()); - } + auto result = m_mwms.insert(id.m_mwmId); + ASSERT(result.second, ()); + lastMwm = id.m_mwmId; + } + m_featureInfo.push_back(id); + }, GetGlobalRect(), GetZoomLevel()); } void TileInfo::ReadFeatures(MapDataProvider const & model) @@ -68,13 +63,14 @@ void TileInfo::ReadFeatures(MapDataProvider const & model) ReadFeatureIndex(model); CheckCanceled(); + m_context->GetMetalineManager()->Update(m_mwms); + if (!m_featureInfo.empty()) { auto const deviceLang = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()); RuleDrawer drawer(std::bind(&TileInfo::InitStylist, this, deviceLang, _1, _2), std::bind(&TileInfo::IsCancelled, this), - model.m_isCountryLoadedByName, - make_ref(m_context)); + model.m_isCountryLoadedByName, make_ref(m_context)); model.ReadFeatures(std::bind(std::ref(drawer), _1), m_featureInfo); } #if defined(DRAPE_MEASURER) && defined(TILES_STATISTIC) diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index 0ba44a1cfc..2cab45c011 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -10,6 +10,7 @@ #include "base/macros.hpp" #include +#include #include class FeatureType; @@ -46,6 +47,7 @@ private: drape_ptr m_context; std::vector m_featureInfo; std::atomic m_isCanceled; + std::set m_mwms; DISALLOW_COPY_AND_MOVE(TileInfo); }; diff --git a/geometry/spline.cpp b/geometry/spline.cpp index 29e82aad7e..fd59e3ebe4 100644 --- a/geometry/spline.cpp +++ b/geometry/spline.cpp @@ -284,10 +284,14 @@ Spline * SharedSpline::operator->() } Spline const * SharedSpline::operator->() const +{ + return Get(); +} + +Spline const * SharedSpline::Get() const { ASSERT(!IsNull(), ()); return m_spline.get(); } - } diff --git a/geometry/spline.hpp b/geometry/spline.hpp index 96e82760df..da5879c180 100644 --- a/geometry/spline.hpp +++ b/geometry/spline.hpp @@ -98,6 +98,8 @@ public: Spline * operator->(); Spline const * operator->() const; + Spline const * Get() const; + private: shared_ptr m_spline; }; diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj index f54bd65b57..28da21d59f 100644 --- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj +++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj @@ -216,6 +216,10 @@ BB035F6F1E3A2AAE00519962 /* drape_measurer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */; }; BB035F701E3A2AAE00519962 /* drape_measurer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */; }; BBD8F8791E96A51A00BAEB72 /* drape_hints.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBD8F8781E96A51A00BAEB72 /* drape_hints.hpp */; }; + EB2B77FF1EEDD418002697B6 /* metaline_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB2B77FD1EEDD418002697B6 /* metaline_manager.cpp */; }; + EB2B78001EEDD418002697B6 /* metaline_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB2B77FE1EEDD418002697B6 /* metaline_manager.hpp */; }; + EB2B78031EEDD439002697B6 /* read_metaline_task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB2B78011EEDD439002697B6 /* read_metaline_task.cpp */; }; + EB2B78041EEDD439002697B6 /* read_metaline_task.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB2B78021EEDD439002697B6 /* read_metaline_task.hpp */; }; F6B283101C1B04680081957A /* gps_track_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B2830B1C1B04680081957A /* gps_track_point.hpp */; }; F6B283111C1B04680081957A /* gps_track_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B2830C1C1B04680081957A /* gps_track_renderer.cpp */; }; F6B283121C1B04680081957A /* gps_track_renderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B2830D1C1B04680081957A /* gps_track_renderer.hpp */; }; @@ -506,6 +510,10 @@ BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drape_measurer.cpp; sourceTree = ""; }; BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_measurer.hpp; sourceTree = ""; }; BBD8F8781E96A51A00BAEB72 /* drape_hints.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_hints.hpp; sourceTree = ""; }; + EB2B77FD1EEDD418002697B6 /* metaline_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = metaline_manager.cpp; sourceTree = ""; }; + EB2B77FE1EEDD418002697B6 /* metaline_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = metaline_manager.hpp; sourceTree = ""; }; + EB2B78011EEDD439002697B6 /* read_metaline_task.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = read_metaline_task.cpp; sourceTree = ""; }; + EB2B78021EEDD439002697B6 /* read_metaline_task.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = read_metaline_task.hpp; sourceTree = ""; }; F6B2830B1C1B04680081957A /* gps_track_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_track_point.hpp; sourceTree = ""; }; F6B2830C1C1B04680081957A /* gps_track_renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gps_track_renderer.cpp; sourceTree = ""; }; F6B2830D1C1B04680081957A /* gps_track_renderer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_track_renderer.hpp; sourceTree = ""; }; @@ -609,6 +617,10 @@ 670947411BDF9B99005014C0 /* drape_frontend */ = { isa = PBXGroup; children = ( + EB2B78011EEDD439002697B6 /* read_metaline_task.cpp */, + EB2B78021EEDD439002697B6 /* read_metaline_task.hpp */, + EB2B77FD1EEDD418002697B6 /* metaline_manager.cpp */, + EB2B77FE1EEDD418002697B6 /* metaline_manager.hpp */, 451A2A801EE8464E003E05A4 /* circles_pack_shape.cpp */, 451A2A811EE8464E003E05A4 /* circles_pack_shape.hpp */, 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */, @@ -860,6 +872,7 @@ files = ( 670947971BDF9BE1005014C0 /* line_shape.hpp in Headers */, 56BF56DB1C7608C0006DD7CB /* choose_position_mark.hpp in Headers */, + EB2B78001EEDD418002697B6 /* metaline_manager.hpp in Headers */, 45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */, 670948031BDF9BF5005014C0 /* drape_engine.hpp in Headers */, 6709486A1BDF9C7F005014C0 /* brush_info.hpp in Headers */, @@ -901,6 +914,7 @@ 457D89251E7AE89500049500 /* custom_symbol.hpp in Headers */, 675D218D1BFB871D00717E4F /* proto_to_styles.hpp in Headers */, 670947951BDF9BE1005014C0 /* line_shape_helper.hpp in Headers */, + EB2B78041EEDD439002697B6 /* read_metaline_task.hpp in Headers */, 670948501BDF9C48005014C0 /* skin.hpp in Headers */, 56D545671C74A44900E3719C /* overlay_batcher.hpp in Headers */, 670947B21BDF9BE1005014C0 /* read_mwm_task.hpp in Headers */, @@ -1090,10 +1104,12 @@ 670947FA1BDF9BF5005014C0 /* backend_renderer.cpp in Sources */, 45BB025D1EB8BE5200FE5C0C /* shader_def.cpp in Sources */, 670948451BDF9C48005014C0 /* gui_text.cpp in Sources */, + EB2B78031EEDD439002697B6 /* read_metaline_task.cpp in Sources */, 670948141BDF9C39005014C0 /* base_interpolator.cpp in Sources */, 670948491BDF9C48005014C0 /* ruler_helper.cpp in Sources */, 670947E41BDF9BEC005014C0 /* engine_context.cpp in Sources */, 670947B51BDF9BE1005014C0 /* render_node.cpp in Sources */, + EB2B77FF1EEDD418002697B6 /* metaline_manager.cpp in Sources */, 670947AF1BDF9BE1005014C0 /* read_manager.cpp in Sources */, 670947941BDF9BE1005014C0 /* line_shape_helper.cpp in Sources */, 670947C21BDF9BE1005014C0 /* stylist.cpp in Sources */,