diff options
Diffstat (limited to 'drape/glyph_manager.cpp')
-rw-r--r-- | drape/glyph_manager.cpp | 110 |
1 files changed, 77 insertions, 33 deletions
diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp index 32556a3075..cf5330c1d9 100644 --- a/drape/glyph_manager.cpp +++ b/drape/glyph_manager.cpp @@ -66,6 +66,7 @@ namespace { uint32_t const kSdfBorder = 4; +double const kNonSdfBorder = 0.2; int const kInvalidFont = -1; template <typename ToDo> @@ -182,9 +183,11 @@ public: return FT_Get_Char_Index(m_fontFace, unicodePoint) != 0; } - GlyphManager::Glyph GetGlyph(strings::UniChar unicodePoint, uint32_t baseHeight) const + GlyphManager::Glyph GetGlyph(strings::UniChar unicodePoint, uint32_t baseHeight, bool isSdf) const { - FREETYPE_CHECK(FT_Set_Pixel_Sizes(m_fontFace, m_sdfScale * baseHeight, m_sdfScale * baseHeight)); + uint32_t glyphHeight = isSdf ? baseHeight * m_sdfScale : baseHeight; + + FREETYPE_CHECK(FT_Set_Pixel_Sizes(m_fontFace, glyphHeight, glyphHeight)); FREETYPE_CHECK(FT_Load_Glyph(m_fontFace, FT_Get_Char_Index(m_fontFace, unicodePoint), FT_LOAD_RENDER)); FT_Glyph glyph; @@ -195,20 +198,42 @@ public: FT_Bitmap bitmap = m_fontFace->glyph->bitmap; - float const scale = 1.0f / m_sdfScale; + float const scale = isSdf ? 1.0f / m_sdfScale : 1.0; SharedBufferManager::shared_buffer_ptr_t data; int imageWidth = bitmap.width; int imageHeight = bitmap.rows; + int border = 0; if (bitmap.buffer != nullptr) { - sdf_image::SdfImage img(bitmap.rows, bitmap.pitch, bitmap.buffer, m_sdfScale * kSdfBorder); - imageWidth = img.GetWidth() * scale; - imageHeight = img.GetHeight() * scale; + if (isSdf) + { + sdf_image::SdfImage img(bitmap.rows, bitmap.pitch, bitmap.buffer, m_sdfScale * kSdfBorder); + imageWidth = img.GetWidth() * scale; + imageHeight = img.GetHeight() * scale; - size_t bufferSize = bitmap.rows * bitmap.pitch; - data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); - memcpy(&(*data)[0], bitmap.buffer, bufferSize); + size_t const bufferSize = bitmap.rows * bitmap.pitch; + data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); + memcpy(&(*data)[0], bitmap.buffer, bufferSize); + } + else + { + border = glyphHeight * kNonSdfBorder; + imageHeight += 2 * border; + imageWidth += 2 * border; + + size_t const bufferSize = imageWidth * imageHeight; + data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); + memset(data->data(), 0, data->size()); + + for (size_t row = border; row < bitmap.rows + border; ++row) + { + size_t const dstBaseIndex = row * imageWidth + border; + size_t const srcBaseIndex = (row - border) * bitmap.pitch; + for (size_t column = 0; column < bitmap.pitch; ++column) + data->data()[dstBaseIndex + column] = bitmap.buffer[srcBaseIndex + column]; + } + } } GlyphManager::Glyph result; @@ -222,13 +247,14 @@ public: result.m_metrics = GlyphManager::GlyphMetrics { static_cast<float>(glyph->advance.x >> 16) * scale, - static_cast<float>(glyph->advance.y >> 16) * scale, - static_cast<float>(bbox.xMin) * scale, - static_cast<float>(bbox.yMin) * scale, + static_cast<float>(glyph->advance.y >> 16) * scale, + static_cast<float>(bbox.xMin) * scale + border, + static_cast<float>(bbox.yMin) * scale + border, true }; result.m_code = unicodePoint; + result.m_fixedSize = isSdf ? GlyphManager::kDynamicGlyphSize : baseHeight; FT_Done_Glyph(glyph); @@ -243,23 +269,35 @@ public: resultGlyph.m_metrics = glyph.m_metrics; resultGlyph.m_fontIndex = glyph.m_fontIndex; resultGlyph.m_code = glyph.m_code; + resultGlyph.m_fixedSize = glyph.m_fixedSize; + + if (glyph.m_fixedSize < 0) + { + sdf_image::SdfImage img(glyph.m_image.m_bitmapRows, glyph.m_image.m_bitmapPitch, + glyph.m_image.m_data->data(), m_sdfScale * kSdfBorder); - sdf_image::SdfImage img(glyph.m_image.m_bitmapRows, glyph.m_image.m_bitmapPitch, - glyph.m_image.m_data->data(), m_sdfScale * kSdfBorder); + img.GenerateSDF(1.0f / (float)m_sdfScale); - img.GenerateSDF(1.0f / (float)m_sdfScale); + ASSERT(img.GetWidth() == glyph.m_image.m_width, ()); + ASSERT(img.GetHeight() == glyph.m_image.m_height, ()); - ASSERT(img.GetWidth() == glyph.m_image.m_width, ()); - ASSERT(img.GetHeight() == glyph.m_image.m_height, ()); + size_t bufferSize = my::NextPowOf2(glyph.m_image.m_width * glyph.m_image.m_height); + resultGlyph.m_image.m_data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); + + img.GetData(*resultGlyph.m_image.m_data); + } + else + { + size_t bufferSize = my::NextPowOf2(glyph.m_image.m_width * glyph.m_image.m_height); + resultGlyph.m_image.m_data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); + resultGlyph.m_image.m_data->assign(glyph.m_image.m_data->begin(), glyph.m_image.m_data->end()); + } - size_t bufferSize = my::NextPowOf2(glyph.m_image.m_width * glyph.m_image.m_height); resultGlyph.m_image.m_width = glyph.m_image.m_width; resultGlyph.m_image.m_height = glyph.m_image.m_height; resultGlyph.m_image.m_bitmapRows = 0; resultGlyph.m_image.m_bitmapPitch = 0; - resultGlyph.m_image.m_data = SharedBufferManager::instance().reserveSharedBuffer(bufferSize); - img.GetData(*resultGlyph.m_image.m_data); return resultGlyph; } return glyph; @@ -289,14 +327,14 @@ public: static void Close(FT_Stream){} - void MarkGlyphReady(strings::UniChar code) + void MarkGlyphReady(strings::UniChar code, int fixedHeight) { - m_readyGlyphs.insert(code); + m_readyGlyphs.insert(make_pair(code, fixedHeight)); } - bool IsGlyphReady(strings::UniChar code) const + bool IsGlyphReady(strings::UniChar code, int fixedHeight) const { - return m_readyGlyphs.find(code) != m_readyGlyphs.end(); + return m_readyGlyphs.find(make_pair(code, fixedHeight)) != m_readyGlyphs.end(); } private: @@ -305,7 +343,7 @@ private: FT_Face m_fontFace; uint32_t m_sdfScale; - unordered_set<strings::UniChar> m_readyGlyphs; + std::set<pair<strings::UniChar, int>> m_readyGlyphs; }; } @@ -359,6 +397,8 @@ struct UnicodeBlock typedef vector<UnicodeBlock> TUniBlocks; typedef TUniBlocks::const_iterator TUniBlockIter; +const int GlyphManager::kDynamicGlyphSize = -1; + struct GlyphManager::Impl { FT_Library m_library; @@ -561,14 +601,15 @@ int GlyphManager::FindFontIndexInBlock(UnicodeBlock const & block, strings::UniC return kInvalidFont; } -GlyphManager::Glyph GlyphManager::GetGlyph(strings::UniChar unicodePoint) +GlyphManager::Glyph GlyphManager::GetGlyph(strings::UniChar unicodePoint, int fixedHeight) { int const fontIndex = GetFontIndex(unicodePoint); if (fontIndex == kInvalidFont) - return GetInvalidGlyph(); + return GetInvalidGlyph(fixedHeight); auto const & f = m_impl->m_fonts[fontIndex]; - Glyph glyph = f->GetGlyph(unicodePoint, m_impl->m_baseGlyphHeight); + bool const isSdf = fixedHeight < 0; + Glyph glyph = f->GetGlyph(unicodePoint, isSdf ? m_impl->m_baseGlyphHeight : fixedHeight, isSdf); glyph.m_fontIndex = fontIndex; return glyph; } @@ -591,10 +632,10 @@ void GlyphManager::MarkGlyphReady(Glyph const & glyph) { ASSERT_GREATER_OR_EQUAL(glyph.m_fontIndex, 0, ()); ASSERT_LESS(glyph.m_fontIndex, m_impl->m_fonts.size(), ()); - m_impl->m_fonts[glyph.m_fontIndex]->MarkGlyphReady(glyph.m_code); + m_impl->m_fonts[glyph.m_fontIndex]->MarkGlyphReady(glyph.m_code, glyph.m_fixedSize); } -bool GlyphManager::AreGlyphsReady(strings::UniString const & str) const +bool GlyphManager::AreGlyphsReady(strings::UniString const & str, int fixedSize) const { for (auto const & code : str) { @@ -602,14 +643,14 @@ bool GlyphManager::AreGlyphsReady(strings::UniString const & str) const if (fontIndex == kInvalidFont) continue; - if (!m_impl->m_fonts[fontIndex]->IsGlyphReady(code)) + if (!m_impl->m_fonts[fontIndex]->IsGlyphReady(code, fixedSize)) return false; } return true; } -GlyphManager::Glyph GlyphManager::GetInvalidGlyph() const +GlyphManager::Glyph GlyphManager::GetInvalidGlyph(int fixedSize) const { strings::UniChar const kInvalidGlyphCode = 0x9; int const kFontId = 0; @@ -620,7 +661,10 @@ GlyphManager::Glyph GlyphManager::GetInvalidGlyph() const if (!s_inited) { ASSERT(!m_impl->m_fonts.empty(), ()); - s_glyph = m_impl->m_fonts[kFontId]->GetGlyph(kInvalidGlyphCode, m_impl->m_baseGlyphHeight); + bool const isSdf = fixedSize < 0 ; + s_glyph = m_impl->m_fonts[kFontId]->GetGlyph(kInvalidGlyphCode, + isSdf ? m_impl->m_baseGlyphHeight : fixedSize, + isSdf); s_glyph.m_metrics.m_isValid = false; s_glyph.m_fontIndex = kFontId; s_glyph.m_code = kInvalidGlyphCode; |