Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/drape
diff options
context:
space:
mode:
authorr.kuznetsov <r.kuznetsov@corp.mail.ru>2016-04-08 14:13:45 +0300
committerr.kuznetsov <r.kuznetsov@corp.mail.ru>2016-04-08 16:22:40 +0300
commitdff324286469b406e7a36c55a35b22db22ac3034 (patch)
treede730e6853ce9da2a2c4b194a8c738aa5bf99378 /drape
parentf116819e8df1ceba1fa25e018ffb0728cccea683 (diff)
Fixed packing glyphs
Diffstat (limited to 'drape')
-rw-r--r--drape/font_texture.cpp46
-rw-r--r--drape/font_texture.hpp15
-rw-r--r--drape/glyph_manager.cpp5
-rw-r--r--drape/glyph_manager.hpp2
-rw-r--r--drape/texture.hpp1
-rw-r--r--drape/texture_manager.cpp40
-rw-r--r--drape/texture_manager.hpp15
7 files changed, 117 insertions, 7 deletions
diff --git a/drape/font_texture.cpp b/drape/font_texture.cpp
index 865aa46745..65365fc6cb 100644
--- a/drape/font_texture.cpp
+++ b/drape/font_texture.cpp
@@ -49,6 +49,28 @@ bool GlyphPacker::PackGlyph(uint32_t width, uint32_t height, m2::RectU & rect)
return true;
}
+bool GlyphPacker::CanBePacked(uint32_t glyphsCount, uint32_t width, uint32_t height) const
+{
+ uint32_t x = m_cursor.x;
+ uint32_t y = m_cursor.y;
+ uint32_t step = m_yStep;
+ for (uint32_t i = 0; i < glyphsCount; i++)
+ {
+ if (x + width > m_size.x)
+ {
+ x = 0;
+ y += step;
+ }
+
+ if (y + height > m_size.y)
+ return false;
+
+ x += width;
+ step = max(height, step);
+ }
+ return true;
+}
+
m2::RectF GlyphPacker::MapTextureCoords(const m2::RectU & pixelRect) const
{
float fWidth = static_cast<float>(m_size.x);
@@ -184,6 +206,19 @@ ref_ptr<Texture::ResourceInfo> GlyphIndex::MapResource(GlyphKey const & key, boo
return make_ref(&res.first->second);
}
+bool GlyphIndex::CanBeGlyphPacked(uint32_t glyphsCount) const
+{
+ if (glyphsCount == 0)
+ return true;
+
+ if (m_packer.IsFull())
+ return false;
+
+ float const kGlyphScalar = 1.5f;
+ uint32_t const baseSize = static_cast<uint32_t>(m_mng->GetBaseGlyphHeight() * kGlyphScalar);
+ return m_packer.CanBePacked(glyphsCount, baseSize, baseSize);
+}
+
bool GlyphIndex::HasAsyncRoutines() const
{
return !m_generator->IsSuspended();
@@ -245,4 +280,15 @@ void GlyphIndex::UploadResources(ref_ptr<Texture> texture)
}
}
+uint32_t GlyphIndex::GetAbsentGlyphsCount(strings::UniString const & text) const
+{
+ uint32_t count = 0;
+ for (strings::UniChar const & c : text)
+ {
+ if (m_index.find(c) == m_index.end())
+ count++;
+ }
+ return count;
+}
+
} // namespace dp
diff --git a/drape/font_texture.hpp b/drape/font_texture.hpp
index 89b13d5261..7790d2213c 100644
--- a/drape/font_texture.hpp
+++ b/drape/font_texture.hpp
@@ -22,6 +22,7 @@ public:
GlyphPacker(m2::PointU const & size);
bool PackGlyph(uint32_t width, uint32_t height, m2::RectU & rect);
+ bool CanBePacked(uint32_t glyphsCount, uint32_t width, uint32_t height) const;
m2::RectF MapTextureCoords(m2::RectU const & pixelRect) const;
bool IsFull() const;
@@ -108,8 +109,12 @@ public:
ref_ptr<Texture::ResourceInfo> MapResource(GlyphKey const & key, bool & newResource);
void UploadResources(ref_ptr<Texture> texture);
+ bool CanBeGlyphPacked(uint32_t glyphsCount) const;
+
bool HasAsyncRoutines() const;
+ uint32_t GetAbsentGlyphsCount(strings::UniString const & text) const;
+
// ONLY for unit-tests. DO NOT use this function anywhere else.
size_t GetPendingNodesCount();
@@ -147,11 +152,21 @@ public:
~FontTexture() { TBase::Reset(); }
+ bool IsFull(uint32_t newKeysCount) const override
+ {
+ return !m_index.CanBeGlyphPacked(newKeysCount);
+ }
+
bool HasAsyncRoutines() const override
{
return m_index.HasAsyncRoutines();
}
+ uint32_t GetAbsentGlyphsCount(strings::UniString const & text) const
+ {
+ return m_index.GetAbsentGlyphsCount(text);
+ }
+
private:
GlyphIndex m_index;
};
diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp
index cf0c59d468..809e27f58b 100644
--- a/drape/glyph_manager.cpp
+++ b/drape/glyph_manager.cpp
@@ -499,6 +499,11 @@ GlyphManager::~GlyphManager()
delete m_impl;
}
+uint32_t GlyphManager::GetBaseGlyphHeight() const
+{
+ return m_impl->m_baseGlyphHeight;
+}
+
int GlyphManager::GetFontIndex(strings::UniChar unicodePoint)
{
TUniBlockIter iter = m_impl->m_blocks.end();
diff --git a/drape/glyph_manager.hpp b/drape/glyph_manager.hpp
index 3ff27ba265..0c28b373dc 100644
--- a/drape/glyph_manager.hpp
+++ b/drape/glyph_manager.hpp
@@ -85,6 +85,8 @@ public:
Glyph GetInvalidGlyph() const;
+ uint32_t GetBaseGlyphHeight() const;
+
private:
int GetFontIndex(strings::UniChar unicodePoint);
// Immutable version can be called from any thread and doesn't require internal synchronization.
diff --git a/drape/texture.hpp b/drape/texture.hpp
index c88cf4d737..b59834920b 100644
--- a/drape/texture.hpp
+++ b/drape/texture.hpp
@@ -51,6 +51,7 @@ public:
virtual ref_ptr<ResourceInfo> FindResource(Key const & key, bool & newResource) = 0;
virtual void UpdateState() {}
virtual bool HasAsyncRoutines() const { return false; }
+ virtual bool IsFull(uint32_t newKeysCount) const { return false; }
using Params = HWTexture::Params;
diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp
index 16fda6bfcb..46e333d97c 100644
--- a/drape/texture_manager.cpp
+++ b/drape/texture_manager.cpp
@@ -334,10 +334,18 @@ size_t TextureManager::FindHybridGlyphsGroup(strings::UniString const & text)
return 0;
}
+ HybridGlyphGroup & group = m_hybridGlyphGroups.back();
+ bool isFull = false;
+ if (group.m_texture != nullptr)
+ isFull = group.m_texture->IsFull(text.size());
+
// if we have got the only hybrid texture (in most cases it is) we can omit checking of glyphs usage
- size_t const glyphsCount = m_hybridGlyphGroups.back().m_glyphs.size() + text.size();
- if (m_hybridGlyphGroups.size() == 1 && glyphsCount < m_maxGlypsCount)
- return 0;
+ if (!isFull)
+ {
+ size_t const glyphsCount = group.m_glyphs.size() + text.size();
+ if (m_hybridGlyphGroups.size() == 1 && glyphsCount < m_maxGlypsCount)
+ return 0;
+ }
// looking for a hybrid texture which contains text entirely
for (size_t i = 0; i < m_hybridGlyphGroups.size() - 1; i++)
@@ -345,9 +353,9 @@ size_t TextureManager::FindHybridGlyphsGroup(strings::UniString const & text)
return i;
// check if we can contain text in the last hybrid texture
- size_t const unfoundChars = GetNumberOfUnfoundCharacters(text, m_hybridGlyphGroups.back());
- size_t const newCharsCount = m_hybridGlyphGroups.back().m_glyphs.size() + unfoundChars;
- if (newCharsCount >= m_maxGlypsCount)
+ size_t const unfoundChars = GetNumberOfUnfoundCharacters(text, group);
+ size_t const newCharsCount = group.m_glyphs.size() + unfoundChars;
+ if (newCharsCount >= m_maxGlypsCount || group.m_texture->IsFull(unfoundChars))
m_hybridGlyphGroups.push_back(HybridGlyphGroup());
return m_hybridGlyphGroups.size() - 1;
@@ -469,6 +477,26 @@ void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuf
CalcGlyphRegions<strings::UniString, TGlyphsBuffer>(text, regions);
}
+uint32_t TextureManager::GetAbsentGlyphsCount(ref_ptr<Texture> texture, strings::UniString const & text)
+{
+ if (texture == nullptr)
+ return 0;
+
+ ASSERT(dynamic_cast<FontTexture *>(texture.get()) != nullptr, ());
+ return static_cast<FontTexture *>(texture.get())->GetAbsentGlyphsCount(text);
+}
+
+uint32_t TextureManager::GetAbsentGlyphsCount(ref_ptr<Texture> texture, TMultilineText const & text)
+{
+ if (texture == nullptr)
+ return 0;
+
+ uint32_t count = 0;
+ for (size_t i = 0; i < text.size(); ++i)
+ count += GetAbsentGlyphsCount(texture, text[i]);
+ return count;
+}
+
bool TextureManager::AreGlyphsReady(strings::UniString const & str) const
{
return m_glyphManager->AreGlyphsReady(str);
diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp
index 5851087ce8..c8be6d6566 100644
--- a/drape/texture_manager.hpp
+++ b/drape/texture_manager.hpp
@@ -186,13 +186,23 @@ private:
void CalcGlyphRegions(TText const & text, TBuffer & buffers)
{
size_t const groupIndex = FindGlyphsGroup(text);
+ bool useHybridGroup = false;
if (groupIndex != GetInvalidGlyphGroup())
{
GlyphGroup & group = m_glyphGroups[groupIndex];
- FillResults<GlyphGroup>(text, buffers, group);
+ uint32_t const absentGlyphs = GetAbsentGlyphsCount(group.m_texture, text);
+ if (group.m_texture == nullptr || !group.m_texture->IsFull(absentGlyphs))
+ FillResults<GlyphGroup>(text, buffers, group);
+ else
+ useHybridGroup = true;
}
else
{
+ useHybridGroup = true;
+ }
+
+ if (useHybridGroup)
+ {
size_t const hybridGroupIndex = FindHybridGlyphsGroup(text);
ASSERT(hybridGroupIndex != GetInvalidGlyphGroup(), ());
HybridGlyphGroup & group = m_hybridGlyphGroups[hybridGroupIndex];
@@ -200,6 +210,9 @@ private:
}
}
+ uint32_t GetAbsentGlyphsCount(ref_ptr<Texture> texture, strings::UniString const & text);
+ uint32_t GetAbsentGlyphsCount(ref_ptr<Texture> texture, TMultilineText const & text);
+
template<typename TGlyphGroups>
void UpdateGlyphTextures(TGlyphGroups & groups)
{