From b7a874d09d583864b7e1b7b84cf0de26a05c3d50 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Thu, 15 Feb 2018 13:16:26 +0300 Subject: Extracted glyph generator from font textures --- drape/glyph_generator.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 drape/glyph_generator.cpp (limited to 'drape/glyph_generator.cpp') diff --git a/drape/glyph_generator.cpp b/drape/glyph_generator.cpp new file mode 100644 index 0000000000..cf19708674 --- /dev/null +++ b/drape/glyph_generator.cpp @@ -0,0 +1,131 @@ +#include "drape/glyph_generator.hpp" + +#include + +using namespace std::placeholders; + +namespace dp +{ +GlyphGenerator::GlyphGenerator(uint32_t sdfScale) + : m_sdfScale(sdfScale) +{} + +GlyphGenerator::~GlyphGenerator() +{ + { + std::lock_guard lock(m_mutex); + m_listeners.clear(); + } + + // Here we have to wait for active tasks completion, + // because they capture 'this' pointer. + m_activeTasks.FinishAll(); + + std::lock_guard lock(m_mutex); + for (auto & data : m_queue) + data.DestroyGlyph(); +} + +bool GlyphGenerator::IsSuspended() const +{ + std::lock_guard lock(m_mutex); + return m_glyphsCounter == 0; +} + +void GlyphGenerator::RegisterListener(ref_ptr listener) +{ + std::lock_guard lock(m_mutex); + m_listeners.insert(listener); +} + +void GlyphGenerator::UnregisterListener(ref_ptr listener) +{ + std::lock_guard lock(m_mutex); + m_listeners.erase(listener); +} + +void GlyphGenerator::GenerateGlyph(ref_ptr listener, m2::RectU const & rect, + GlyphManager::Glyph & glyph) +{ + GenerateGlyph(listener, GlyphGenerationData(rect, glyph)); +} + +void GlyphGenerator::GenerateGlyph(ref_ptr listener, GlyphGenerationData && data) +{ + GenerateGlyphs(listener, {std::move(data)}); +} + +void GlyphGenerator::GenerateGlyphs(ref_ptr listener, + GlyphGenerationDataArray && generationData) +{ + std::lock_guard lock(m_mutex); + if (m_listeners.find(listener) == m_listeners.end()) + { + for (auto & data : generationData) + data.DestroyGlyph(); + return; + } + + GlyphGenerationDataArray queue; + std::move(generationData.begin(), generationData.end(), std::back_inserter(m_queue)); + std::swap(m_queue, queue); + m_glyphsCounter += queue.size(); + + // Generate glyphs on the separate thread. + auto generateTask = std::make_shared(std::move(queue)); + auto result = DrapeRoutine::Run([this, listener, generateTask]() mutable + { + generateTask->Run(m_sdfScale); + OnTaskFinished(listener, generateTask); + }); + + if (result) + m_activeTasks.Add(generateTask, result); + else + generateTask->DestroyAllGlyphs(); +} + +void GlyphGenerator::OnTaskFinished(ref_ptr listener, + std::shared_ptr const & task) +{ + if (task->IsCancelled()) + { + task->DestroyAllGlyphs(); + return; + } + + auto glyphs = task->StealGeneratedGlyphs(); + + std::lock_guard lock(m_mutex); + ASSERT_GREATER_OR_EQUAL(m_glyphsCounter, glyphs.size(), ()); + m_glyphsCounter -= glyphs.size(); + + if (m_listeners.find(listener) != m_listeners.end()) + listener->OnCompleteGlyphGeneration(std::move(glyphs)); + + m_activeTasks.Remove(task); +} + +void GlyphGenerator::GenerateGlyphTask::Run(uint32_t sdfScale) +{ + m_generatedGlyphs.reserve(m_glyphs.size()); + for (auto & data : m_glyphs) + { + if (m_isCancelled) + return; + + auto const g = GlyphManager::GenerateGlyph(data.m_glyph, sdfScale); + data.DestroyGlyph(); + m_generatedGlyphs.emplace_back(GlyphGenerator::GlyphGenerationData{data.m_rect, g}); + } +} + +void GlyphGenerator::GenerateGlyphTask::DestroyAllGlyphs() +{ + for (auto & data : m_glyphs) + data.DestroyGlyph(); + + for (auto & data : m_generatedGlyphs) + data.DestroyGlyph(); +} +} // namespace dp -- cgit v1.2.3