#pragma once #include "drape/color.hpp" #include "drape/glyph_generator.hpp" #include "drape/glyph_manager.hpp" #include "drape/pointers.hpp" #include "drape/texture.hpp" #include "drape/font_texture.hpp" #include "base/string_utils.hpp" #include "base/timer.hpp" #include #include #include #include #include #include namespace dp { extern std::string const kDefaultSymbolsTexture; class HWTextureAllocator; class TextureManager { public: class BaseRegion { public: BaseRegion(); void SetResourceInfo(ref_ptr info); void SetTexture(ref_ptr texture); ref_ptr GetTexture() const { return m_texture; } bool IsValid() const; m2::PointF GetPixelSize() const; float GetPixelHeight() const; m2::RectF const & GetTexRect() const; protected: ref_ptr m_info; ref_ptr m_texture; }; class SymbolRegion : public BaseRegion { public: uint32_t GetTextureIndex() const { return m_textureIndex; } void SetTextureIndex(uint32_t index) { m_textureIndex = index; } private: uint32_t m_textureIndex = 0; }; class GlyphRegion : public BaseRegion { public: GlyphRegion(); float GetOffsetX() const; float GetOffsetY() const; float GetAdvanceX() const; float GetAdvanceY() const; }; class StippleRegion : public BaseRegion { public: StippleRegion() : BaseRegion() {} uint32_t GetMaskPixelLength() const; uint32_t GetPatternPixelLength() const; }; class ColorRegion : public BaseRegion { public: ColorRegion() : BaseRegion() {} }; struct Params { std::string m_resPostfix; double m_visualScale = 1.0; std::string m_colors; std::string m_patterns; GlyphManager::Params m_glyphMngParams; }; explicit TextureManager(ref_ptr glyphGenerator); void Release(); void Init(ref_ptr context, Params const & params); void OnSwitchMapStyle(ref_ptr context); void GetTexturesToCleanup(std::vector> & textures); void GetSymbolRegion(std::string const & symbolName, SymbolRegion & region); bool HasSymbolRegion(std::string const & symbolName) const; typedef buffer_vector TStipplePattern; void GetStippleRegion(TStipplePattern const & pen, StippleRegion & region); void GetColorRegion(Color const & color, ColorRegion & region); using TMultilineText = buffer_vector; using TGlyphsBuffer = buffer_vector; using TMultilineGlyphsBuffer = buffer_vector; void GetGlyphRegions(TMultilineText const & text, int fixedHeight, TMultilineGlyphsBuffer & buffers); void GetGlyphRegions(strings::UniString const & text, int fixedHeight, TGlyphsBuffer & regions); // This method must be called only on Frontend renderer's thread. bool AreGlyphsReady(strings::UniString const & str, int fixedHeight) const; // On some devices OpenGL driver can't resolve situation when we upload to a texture on a thread // and use this texture to render on another thread. By this we move UpdateDynamicTextures call // into render thread. If you implement some kind of dynamic texture, you must synchronize UploadData // and index creation operations. // The result of the method shows if there are some changes in texture manager. bool UpdateDynamicTextures(ref_ptr context); ref_ptr GetSymbolsTexture() const; ref_ptr GetTrafficArrowTexture() const; ref_ptr GetHatchingTexture() const; ref_ptr GetSMAAAreaTexture() const; ref_ptr GetSMAASearchTexture() const; private: struct GlyphGroup { GlyphGroup() : m_startChar(0), m_endChar(0), m_texture(nullptr) {} GlyphGroup(strings::UniChar const & start, strings::UniChar const & end) : m_startChar(start), m_endChar(end), m_texture(nullptr) {} strings::UniChar m_startChar; strings::UniChar m_endChar; ref_ptr m_texture; }; struct HybridGlyphGroup { HybridGlyphGroup() : m_texture(nullptr) {} std::set> m_glyphs; ref_ptr m_texture; }; uint32_t m_maxTextureSize; uint32_t m_maxGlypsCount; ref_ptr AllocateGlyphTexture(); void GetRegionBase(ref_ptr tex, TextureManager::BaseRegion & region, Texture::Key const & key); void GetGlyphsRegions(ref_ptr tex, strings::UniString const & text, int fixedHeight, TGlyphsBuffer & regions); size_t FindHybridGlyphsGroup(strings::UniString const & text, int fixedHeight); size_t FindHybridGlyphsGroup(TMultilineText const & text, int fixedHeight); uint32_t GetNumberOfUnfoundCharacters(strings::UniString const & text, int fixedHeight, HybridGlyphGroup const & group) const; void MarkCharactersUsage(strings::UniString const & text, int fixedHeight, HybridGlyphGroup & group); // It's a dummy method to support generic code. void MarkCharactersUsage(strings::UniString const & text, int fixedHeight, GlyphGroup & group) {} template void FillResultBuffer(strings::UniString const & text, int fixedHeight, TGlyphGroup & group, TGlyphsBuffer & regions) { if (group.m_texture == nullptr) group.m_texture = AllocateGlyphTexture(); GetGlyphsRegions(group.m_texture, text, fixedHeight, regions); } template void FillResults(strings::UniString const & text, int fixedHeight, TGlyphsBuffer & buffers, TGlyphGroup & group) { MarkCharactersUsage(text, fixedHeight, group); FillResultBuffer(text, fixedHeight, group, buffers); } template void FillResults(TMultilineText const & text, int fixedHeight, TMultilineGlyphsBuffer & buffers, TGlyphGroup & group) { buffers.resize(text.size()); for (size_t i = 0; i < text.size(); ++i) { strings::UniString const & str = text[i]; TGlyphsBuffer & buffer = buffers[i]; FillResults(str, fixedHeight, buffer, group); } } template void CalcGlyphRegions(TText const & text, int fixedHeight, TBuffer & buffers) { CHECK(m_isInitialized, ()); size_t const hybridGroupIndex = FindHybridGlyphsGroup(text, fixedHeight); ASSERT(hybridGroupIndex != GetInvalidGlyphGroup(), ()); HybridGlyphGroup & group = m_hybridGlyphGroups[hybridGroupIndex]; FillResults(text, fixedHeight, buffers, group); } uint32_t GetAbsentGlyphsCount(ref_ptr texture, strings::UniString const & text, int fixedHeight) const; uint32_t GetAbsentGlyphsCount(ref_ptr texture, TMultilineText const & text, int fixedHeight) const; void UpdateGlyphTextures(ref_ptr context); bool HasAsyncRoutines() const; static constexpr size_t GetInvalidGlyphGroup(); private: bool m_isInitialized = false; ref_ptr m_glyphGenerator; std::string m_resPostfix; std::vector> m_symbolTextures; drape_ptr m_stipplePenTexture; drape_ptr m_colorTexture; std::list> m_glyphTextures; mutable std::mutex m_glyphTexturesMutex; drape_ptr m_trafficArrowTexture; drape_ptr m_hatchingTexture; drape_ptr m_smaaAreaTexture; drape_ptr m_smaaSearchTexture; drape_ptr m_glyphManager; drape_ptr m_textureAllocator; buffer_vector m_hybridGlyphGroups; std::vector> m_texturesToCleanup; base::Timer m_uploadTimer; std::atomic_flag m_nothingToUpload; std::mutex m_calcGlyphsMutex; }; } // namespace dp