/
githubmirror
/
omim
Обзор
Документация
Войти
/
githubmirror
/
omim
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
android-943
drape/symbols_texture.cpp
318 строк
9 KB
r.kuznetsov
[drape] Fixed update map style
17 май 2019, 18:45
17 май 2019, 18:45
1a69dca
Код
Авторство
О чём код?
#include "drape/symbols_texture.hpp" #include "3party/stb_image/stb_image.h" #include "indexer/map_style_reader.hpp" #include "platform/platform.hpp" #include "coding/reader.hpp" #include "coding/parse_xml.hpp" #include "base/string_utils.hpp" #ifdef DEBUG #include "3party/glm/glm/gtx/bit.hpp" #endif #include <functional> #include <utility> namespace dp { namespace { using TDefinitionInserter = std::function<void(std::string const &, m2::RectF const &)>; using TSymbolsLoadingCompletion = std::function<void(unsigned char *, uint32_t, uint32_t)>; using TSymbolsLoadingFailure = std::function<void(std::string const &)>; class DefinitionLoader { public: DefinitionLoader(TDefinitionInserter const & definitionInserter, bool convertToUV) : m_definitionInserter(definitionInserter) , m_convertToUV(convertToUV) , m_width(0) , m_height(0) {} bool Push(std::string const & /*element*/) { return true; } void Pop(std::string const & element) { if (element == "symbol") { ASSERT(!m_name.empty(), ()); ASSERT(m_rect.IsValid(), ()); ASSERT(m_definitionInserter != nullptr, ()); m_definitionInserter(m_name, m_rect); m_name = ""; m_rect.MakeEmpty(); } } void AddAttr(std::string const & attribute, std::string const & value) { if (attribute == "name") m_name = value; else { int v; if (!strings::to_int(value, v)) return; if (attribute == "minX") { ASSERT(m_width != 0, ()); float const scalar = m_convertToUV ? static_cast<float>(m_width) : 1.0f; m_rect.setMinX(v / scalar); } else if (attribute == "minY") { ASSERT(m_height != 0, ()); float const scalar = m_convertToUV ? static_cast<float>(m_height) : 1.0f; m_rect.setMinY(v / scalar); } else if (attribute == "maxX") { ASSERT(m_width != 0, ()); float const scalar = m_convertToUV ? static_cast<float>(m_width) : 1.0f; m_rect.setMaxX(v / scalar); } else if (attribute == "maxY") { ASSERT(m_height != 0, ()); float const scalar = m_convertToUV ? static_cast<float>(m_height) : 1.0f; m_rect.setMaxY(v / scalar); } else if (attribute == "height") { m_height = v; } else if (attribute == "width") { m_width = v; } } } void CharData(std::string const &) {} uint32_t GetWidth() const { return m_width; } uint32_t GetHeight() const { return m_height; } private: TDefinitionInserter m_definitionInserter; bool m_convertToUV; uint32_t m_width; uint32_t m_height; std::string m_name; m2::RectF m_rect; }; void LoadSymbols(std::string const & skinPathName, std::string const & textureName, bool convertToUV, TDefinitionInserter const & definitionInserter, TSymbolsLoadingCompletion const & completionHandler, TSymbolsLoadingFailure const & failureHandler) { ASSERT(definitionInserter != nullptr, ()); ASSERT(completionHandler != nullptr, ()); ASSERT(failureHandler != nullptr, ()); vector<unsigned char> rawData; uint32_t width, height; try { DefinitionLoader loader(definitionInserter, convertToUV); { ReaderPtr<Reader> reader = GetStyleReader().GetResourceReader(textureName + ".sdf", skinPathName); ReaderSource<ReaderPtr<Reader>> source(reader); if (!ParseXML(source, loader)) { failureHandler("Error parsing skin"); return; } width = loader.GetWidth(); height = loader.GetHeight(); } { ReaderPtr<Reader> reader = GetStyleReader().GetResourceReader(textureName + ".png", skinPathName); size_t const size = static_cast<size_t>(reader.Size()); rawData.resize(size); reader.Read(0, &rawData[0], size); } } catch (RootException & e) { failureHandler(e.what()); return; } int w, h, bpp; unsigned char * data = stbi_load_from_memory(&rawData[0], static_cast<int>(rawData.size()), &w, &h, &bpp, 0); ASSERT_EQUAL(bpp, 4, ("Incorrect symbols texture format")); ASSERT(glm::isPowerOfTwo(w), (w)); ASSERT(glm::isPowerOfTwo(h), (h)); if (width == static_cast<uint32_t>(w) && height == static_cast<uint32_t>(h)) { completionHandler(data, width, height); } else { failureHandler("Error symbols texture creation"); } stbi_image_free(data); } } // namespace SymbolsTexture::SymbolKey::SymbolKey(std::string const & symbolName) : m_symbolName(symbolName) {} Texture::ResourceType SymbolsTexture::SymbolKey::GetType() const { return Texture::ResourceType::Symbol; } std::string const & SymbolsTexture::SymbolKey::GetSymbolName() const { return m_symbolName; } SymbolsTexture::SymbolInfo::SymbolInfo(const m2::RectF & texRect) : ResourceInfo(texRect) {} Texture::ResourceType SymbolsTexture::SymbolInfo::GetType() const { return Texture::ResourceType::Symbol; } SymbolsTexture::SymbolsTexture(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName, std::string const & textureName, ref_ptr<HWTextureAllocator> allocator) : m_name(textureName) { Load(context, skinPathName, allocator); } void SymbolsTexture::Load(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName, ref_ptr<HWTextureAllocator> allocator) { auto definitionInserter = [this](std::string const & name, m2::RectF const & rect) { m_definition.insert(std::make_pair(name, SymbolsTexture::SymbolInfo(rect))); }; auto completionHandler = [this, &allocator, context](unsigned char * data, uint32_t width, uint32_t height) { Texture::Params p; p.m_allocator = allocator; p.m_format = dp::TextureFormat::RGBA8; p.m_width = width; p.m_height = height; Create(context, p, make_ref(data)); }; auto failureHandler = [this, context](std::string const & reason) { LOG(LERROR, (reason)); Fail(context); }; LoadSymbols(skinPathName, m_name, true /* convertToUV */, definitionInserter, completionHandler, failureHandler); } void SymbolsTexture::Invalidate(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName, ref_ptr<HWTextureAllocator> allocator) { Destroy(); m_definition.clear(); Load(context, skinPathName, allocator); } void SymbolsTexture::Invalidate(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName, ref_ptr<HWTextureAllocator> allocator, std::vector<drape_ptr<HWTexture>> & internalTextures) { internalTextures.push_back(std::move(m_hwTexture)); Invalidate(context, skinPathName, allocator); } ref_ptr<Texture::ResourceInfo> SymbolsTexture::FindResource(Texture::Key const & key, bool & newResource) { newResource = false; if (key.GetType() != Texture::ResourceType::Symbol) return nullptr; std::string const & symbolName = static_cast<SymbolKey const &>(key).GetSymbolName(); auto it = m_definition.find(symbolName); ASSERT(it != m_definition.end(), (symbolName)); return make_ref(&it->second); } void SymbolsTexture::Fail(ref_ptr<dp::GraphicsContext> context) { m_definition.clear(); int32_t alphaTexture = 0; Texture::Params p; p.m_allocator = GetDefaultAllocator(context); p.m_format = dp::TextureFormat::RGBA8; p.m_width = 1; p.m_height = 1; Create(context, p, make_ref(&alphaTexture)); } bool SymbolsTexture::IsSymbolContained(std::string const & symbolName) const { return m_definition.find(symbolName) != m_definition.end(); } bool SymbolsTexture::DecodeToMemory(std::string const & skinPathName, std::string const & textureName, vector<uint8_t> & symbolsSkin, std::map<std::string, m2::RectU> & symbolsIndex, uint32_t & skinWidth, uint32_t & skinHeight) { auto definitionInserter = [&symbolsIndex](std::string const & name, m2::RectF const & rect) { symbolsIndex.insert(make_pair(name, m2::RectU(rect))); }; bool result = true; auto completionHandler = [&result, &symbolsSkin, &skinWidth, &skinHeight](unsigned char * data, uint32_t width, uint32_t height) { size_t size = 4 * width * height; symbolsSkin.resize(size); memcpy(symbolsSkin.data(), data, size); skinWidth = width; skinHeight = height; result = true; }; auto failureHandler = [&result](std::string const & reason) { LOG(LERROR, (reason)); result = false; }; LoadSymbols(skinPathName, textureName, false /* convertToUV */, definitionInserter, completionHandler, failureHandler); return result; } } // namespace dp