From 29583912e355b852b6dce8f27c92ab05202e6135 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Fri, 12 Apr 2019 18:35:15 +0300 Subject: [PATCH] [screenshots] Check viewport before taking a screenshot. Wait graphics after user marks updating on BackendRenderer. --- drape_frontend/backend_renderer.cpp | 11 ++++++ drape_frontend/drape_engine.cpp | 2 +- drape_frontend/frontend_renderer.cpp | 3 +- drape_frontend/message.cpp | 1 + map/bookmark_helpers.cpp | 9 +++++ map/bookmark_helpers.hpp | 4 ++ map/bookmark_manager.cpp | 24 ++++++++++++ map/bookmark_manager.hpp | 1 + map/framework.cpp | 26 +++---------- qt/CMakeLists.txt | 5 +++ qt/mainwindow.cpp | 2 +- qt/screenshoter.cpp | 56 ++++++++++++++++++++++++---- qt/screenshoter.hpp | 1 + 13 files changed, 113 insertions(+), 32 deletions(-) diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 5933bc1474..bf957a483f 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -583,6 +583,17 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_LINUX) + case Message::Type::NotifyGraphicsReady: + { + ref_ptr msg = message; + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(msg->GetCallback()), + MessagePriority::Normal); + break; + } +#endif + default: ASSERT(false, ()); break; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index a8dfcb9e0e..f3df0a2554 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -502,7 +502,7 @@ void DrapeEngine::SetModelViewListener(TModelViewListenerFn && fn) #if defined(OMIM_OS_MAC) || defined(OMIM_OS_LINUX) void DrapeEngine::NotifyGraphicsReady(TGraphicsReadyFn const & fn) { - m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp(fn), MessagePriority::Normal); } diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8b8394e78e..5cbb9d0dd8 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1010,7 +1010,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) if (m_graphicsReadyFn) { m_graphicsStage = GraphicsStage::WaitReady; - InvalidateRect(m_userEventStream.GetCurrentScreen().ClipRect()); + if (m_notFinishedTiles.empty()) + InvalidateRect(m_userEventStream.GetCurrentScreen().ClipRect()); } break; } diff --git a/drape_frontend/message.cpp b/drape_frontend/message.cpp index f2f170174b..28c9e2f21f 100644 --- a/drape_frontend/message.cpp +++ b/drape_frontend/message.cpp @@ -96,6 +96,7 @@ std::string DebugPrint(Message::Type msgType) case Message::Type::FlushTransitScheme: return "FlushTransitScheme"; case Message::Type::ShowDebugInfo: return "ShowDebugInfo"; case Message::Type::NotifyRenderThread: return "NotifyRenderThread"; + case Message::Type::NotifyGraphicsReady: return "NotifyGraphicsReady"; } ASSERT(false, ("Unknown message type.")); return "Unknown type"; diff --git a/map/bookmark_helpers.cpp b/map/bookmark_helpers.cpp index bb3770532b..f62f971e57 100644 --- a/map/bookmark_helpers.cpp +++ b/map/bookmark_helpers.cpp @@ -492,3 +492,12 @@ bool IsMyCategory(User const & user, kml::CategoryData const & categoryData) { return IsMyCategory(user.GetUserId(), categoryData); } + +void ExpandBookmarksRectForPreview(m2::RectD & rect) +{ + if (!rect.IsValid()) + return; + + double const kPaddingScale = 1.2; + rect.Scale(kPaddingScale); +} diff --git a/map/bookmark_helpers.hpp b/map/bookmark_helpers.hpp index 0e2c6c022b..8f00203e98 100644 --- a/map/bookmark_helpers.hpp +++ b/map/bookmark_helpers.hpp @@ -6,6 +6,8 @@ #include "coding/reader.hpp" +#include "geometry/rect2d.hpp" + #include #include @@ -52,3 +54,5 @@ bool FromCatalog(kml::FileData const & kmlData); bool FromCatalog(kml::CategoryData const & categoryData, std::string const & serverId); bool IsMyCategory(std::string const & userId, kml::CategoryData const & categoryData); bool IsMyCategory(User const & user, kml::CategoryData const & categoryData); + +void ExpandBookmarksRectForPreview(m2::RectD & rect); diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 82b0fca3e3..8d9284e6a0 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -853,6 +853,30 @@ std::string BookmarkManager::GetCategoryFileName(kml::MarkGroupId categoryId) co return category->GetFileName(); } +m2::RectD BookmarkManager::GetCategoryRect(kml::MarkGroupId categoryId) const +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + auto const category = GetBmCategory(categoryId); + CHECK(category != nullptr, ()); + + m2::RectD rect; + if (category->IsEmpty()) + return rect; + + for (auto markId : category->GetUserMarks()) + { + auto const bookmark = GetBookmark(markId); + rect.Add(bookmark->GetPivot()); + } + for (auto trackId : category->GetUserLines()) + { + auto const track = GetTrack(trackId); + rect.Add(track->GetLimitRect()); + } + + return rect; +} + kml::CategoryData const & BookmarkManager::GetCategoryData(kml::MarkGroupId categoryId) const { CHECK_THREAD_CHECKER(m_threadChecker, ()); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 452a26beb0..8ba99468cb 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -179,6 +179,7 @@ public: std::string GetCategoryName(kml::MarkGroupId categoryId) const; std::string GetCategoryFileName(kml::MarkGroupId categoryId) const; + m2::RectD GetCategoryRect(kml::MarkGroupId categoryId) const; kml::CategoryData const & GetCategoryData(kml::MarkGroupId categoryId) const; kml::MarkGroupId GetCategoryId(std::string const & name) const; diff --git a/map/framework.cpp b/map/framework.cpp index 8c68e3f977..2280c8e0c0 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1103,42 +1103,26 @@ void Framework::ShowBookmark(Bookmark const * mark) void Framework::ShowTrack(kml::TrackId trackId) { - double const kPaddingScale = 1.2; - auto const track = GetBookmarkManager().GetTrack(trackId); if (track == nullptr) return; - StopLocationFollow(); auto rect = track->GetLimitRect(); - rect.Scale(kPaddingScale); + ExpandBookmarksRectForPreview(rect); + StopLocationFollow(); ShowRect(rect); } void Framework::ShowBookmarkCategory(kml::MarkGroupId categoryId, bool animation) { - auto const & bm = GetBookmarkManager(); - if (bm.IsCategoryEmpty(categoryId)) - return; - - m2::RectD rect; - for (auto const id : bm.GetUserMarkIds(categoryId)) - { - auto const bookmark = bm.GetBookmark(id); - rect.Add(bookmark->GetPivot()); - } - for (auto const id : bm.GetTrackIds(categoryId)) - { - auto const track = bm.GetTrack(id); - rect.Add(track->GetLimitRect()); - } + auto rect = GetBookmarkManager().GetCategoryRect(categoryId); if (!rect.IsValid()) return; - double const kPaddingScale = 1.2; + ExpandBookmarksRectForPreview(rect); + StopLocationFollow(); - rect.Scale(kPaddingScale); ShowRect(rect, -1 /* maxScale */, animation); } diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index 9063ddccb4..04122aef9c 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -162,6 +162,11 @@ copy_resources( countries-strings resources-default resources-mdpi_clear + resources-hdpi_clear + resources-xhdpi_clear + resources-xxhdpi_clear + resources-xxxhdpi_clear + resources-6plus_clear cuisine-strings taxi_places eula.html diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index 5272273a22..6736f5fb63 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -81,7 +81,7 @@ MainWindow::MainWindow(Framework & framework, bool apiOpenGLES3, { screenshotParams->m_statusChangedFn = [this](std::string const & state, bool finished) { - statusBar()->showMessage(QString::fromStdString("Screenshot mode. " + state)); + statusBar()->showMessage(QString::fromStdString(state)); if (finished) QCoreApplication::quit(); }; diff --git a/qt/screenshoter.cpp b/qt/screenshoter.cpp index 5bd65a1f7f..c31c3e9265 100644 --- a/qt/screenshoter.cpp +++ b/qt/screenshoter.cpp @@ -37,6 +37,13 @@ void Screenshoter::Start() if (m_screenshotParams.m_dstPath.empty()) m_screenshotParams.m_dstPath = base::JoinPath(m_screenshotParams.m_kmlPath, "screenshots"); + LOG(LINFO, ("\nScreenshoter parameters:" + "\n kml_path:", m_screenshotParams.m_kmlPath, + "\n dst_path:", m_screenshotParams.m_dstPath, + "\n width:", m_screenshotParams.m_width, + "\n height:", m_screenshotParams.m_height, + "\n dpi_scale:", m_screenshotParams.m_dpiScale)); + if (!Platform::IsDirectory(m_screenshotParams.m_kmlPath) || !Platform::MkDirChecked(m_screenshotParams.m_dstPath)) { ChangeState(State::FileError); @@ -60,16 +67,16 @@ void Screenshoter::Start() void Screenshoter::ProcessNextKml() { CHECK_EQUAL(m_state, State::Ready, ()); - ChangeState(State::LoadKml); - std::string const prefix = languages::GetCurrentNorm() + "_"; + std::string const postfix = "_" + languages::GetCurrentNorm(); std::unique_ptr kmlData; while (kmlData == nullptr && !m_filesToProcess.empty()) { auto const filePath = m_filesToProcess.front(); m_filesToProcess.pop_front(); - m_nextScreenshotName = prefix + base::GetNameFromFullPathWithoutExt(filePath); + m_nextScreenshotName = base::GetNameFromFullPathWithoutExt(filePath) + postfix; + ChangeState(State::LoadKml); kmlData = LoadKmlFile(filePath, KmlFileType::Text); if (kmlData != nullptr && kmlData->m_bookmarksData.empty() && kmlData->m_tracksData.empty()) kmlData.reset(); @@ -96,6 +103,11 @@ void Screenshoter::ProcessNextKml() ChangeState(State::WaitPosition); auto const newCatId = bookmarkManager.GetBmGroupsIdList().front(); + + m_dataRect = bookmarkManager.GetCategoryRect(newCatId); + ExpandBookmarksRectForPreview(m_dataRect); + CHECK(m_dataRect.IsValid(), ()); + m_framework.ShowBookmarkCategory(newCatId, false); } @@ -122,7 +134,10 @@ void Screenshoter::PrepareCountries() } if (m_countriesToDownload.empty()) + { + ChangeState(State::WaitGraphics); WaitGraphics(); + } } void Screenshoter::OnCountryChanged(storage::CountryId countryId) @@ -135,7 +150,11 @@ void Screenshoter::OnCountryChanged(storage::CountryId countryId) { m_countriesToDownload.erase(countryId); if (m_countriesToDownload.empty()) - WaitGraphics(); + { + ChangeState(State::WaitGraphics); + auto const kDelay = std::chrono::seconds(3); + GetPlatform().RunDelayedTask(Platform::Thread::File, kDelay, [this]{ WaitGraphics(); }); + } } } @@ -144,7 +163,18 @@ void Screenshoter::OnViewportChanged() if (m_state != State::WaitPosition) return; - PrepareCountries(); + auto const currentViewport = m_framework.GetCurrentViewport(); + + double const kEpsRect = 1e-2; + double const kEpsCenter = 1e-3; + double const minCheckedZoomLevel = 5; + if (m_framework.GetDrawScale() < minCheckedZoomLevel || + (m_dataRect.Center().EqualDxDy(currentViewport.Center(), kEpsCenter) && + (fabs(m_dataRect.SizeX() - currentViewport.SizeX()) < kEpsRect || + fabs(m_dataRect.SizeY() - currentViewport.SizeY()) < kEpsRect))) + { + PrepareCountries(); + } } void Screenshoter::OnGraphicsReady() @@ -158,7 +188,6 @@ void Screenshoter::OnGraphicsReady() void Screenshoter::WaitGraphics() { - ChangeState(State::WaitGraphics); m_framework.NotifyGraphicsReady([this]() { GetPlatform().RunTask(Platform::Thread::Gui, [this] { OnGraphicsReady(); }); @@ -169,10 +198,20 @@ void Screenshoter::SaveScreenshot() { CHECK_EQUAL(m_state, State::Ready, ()); + if (!Platform::MkDirChecked(m_screenshotParams.m_dstPath)) + { + ChangeState(State::FileError); + return; + } + QPixmap pixmap(QSize(m_screenshotParams.m_width, m_screenshotParams.m_height)); m_widget->render(&pixmap, QPoint(), QRegion(m_widget->geometry())); - pixmap.save(QString::fromStdString(base::JoinPath(m_screenshotParams.m_dstPath, m_nextScreenshotName + ".png")), - nullptr, 100); + if (!pixmap.save(QString::fromStdString(base::JoinPath(m_screenshotParams.m_dstPath, m_nextScreenshotName + ".png")), + nullptr, 100)) + { + ChangeState(State::FileError); + return; + } m_nextScreenshotName.clear(); ProcessNextKml(); @@ -186,6 +225,7 @@ void Screenshoter::ChangeState(State newState) std::ostringstream ss; ss << "[" << m_filesCount - m_filesToProcess.size() << "/" << m_filesCount << "] file: " << m_nextScreenshotName << " state: " << DebugPrint(newState); + LOG(LINFO, (ss.str())); m_screenshotParams.m_statusChangedFn(ss.str(), newState == Screenshoter::State::Done); } } diff --git a/qt/screenshoter.hpp b/qt/screenshoter.hpp index b48e010656..71f6b282f6 100644 --- a/qt/screenshoter.hpp +++ b/qt/screenshoter.hpp @@ -70,6 +70,7 @@ private: size_t m_filesCount = 0; std::set m_countriesToDownload; std::string m_nextScreenshotName; + m2::RectD m_dataRect; }; std::string DebugPrint(Screenshoter::State state);