MCPcopy Create free account
hub / github.com/comaps/comaps / ShapeText

Method ShapeText

libs/drape/glyph_manager.cpp:570–635  ·  view source on GitHub ↗

This method is NOT multithreading-safe.

Source from the content-addressed store, hash-verified

568
569 // This method is NOT multithreading-safe.
570 text::TextMetrics GlyphManager::ShapeText(std::string_view utf8, int fontPixelHeight, hb_language_t const textLang)
571 {
572#ifdef DEBUG
573 static int const fontSize = fontPixelHeight;
574 ASSERT_EQUAL(fontSize, fontPixelHeight,
575 ("Cache relies on the same font height/metrics for each glyph", fontSize, fontPixelHeight));
576#endif
577
578 // A simple cache greatly speeds up text metrics calculation. It has 80+% hit ratio in most scenarios.
579 if (auto const found = m_impl->m_textMetricsCache.find(utf8); found != m_impl->m_textMetricsCache.end())
580 return found->second;
581
582 auto const [text, segments] = harfbuzz_shaping::GetTextSegments(utf8);
583
584 text::TextMetrics allGlyphs;
585 // For SplitText it's enough to know if the last visual (first logical) segment is RTL.
586 allGlyphs.m_isRTL = segments.back().m_direction == HB_DIRECTION_RTL;
587
588 allGlyphs.m_glyphs.reserve(strings::CountChar(utf8));
589
590 for (auto const & substring : segments)
591 {
592 hb_buffer_clear_contents(m_impl->m_harfbuzzBuffer);
593
594 // TODO(AB): Some substrings use different fonts.
595 hb_buffer_add_utf16(m_impl->m_harfbuzzBuffer, reinterpret_cast<uint16_t const *>(text.data()),
596 static_cast<int>(text.size()), substring.m_start, substring.m_length);
597 hb_buffer_set_direction(m_impl->m_harfbuzzBuffer, substring.m_direction);
598 hb_buffer_set_script(m_impl->m_harfbuzzBuffer, substring.m_script);
599 hb_buffer_set_language(m_impl->m_harfbuzzBuffer, textLang);
600
601 auto u32CharacterIter{text.begin() + substring.m_start};
602 auto const end{u32CharacterIter + substring.m_length};
603 do
604 {
605 auto const u32Character = utf8::unchecked::next16(u32CharacterIter);
606 // TODO(AB): Mapping characters to fonts can be optimized.
607 int const fontIndex = GetFontIndex(u32Character);
608 if (fontIndex < 0)
609 LOG(LWARNING, ("No font was found for character", NumToHex(u32Character)));
610 else
611 {
612 // TODO(AB): Mapping font only by the first character in a string may fail in theory in some cases.
613 m_impl->m_fonts[fontIndex]->Shape(m_impl->m_harfbuzzBuffer, fontPixelHeight, fontIndex, allGlyphs);
614 break;
615 }
616 }
617 while (u32CharacterIter != end);
618 }
619
620 // Uncomment utf8 printing for debugging if necessary. It crashes JNI with non-modified UTF-8 strings on Android 5
621 // and 6. See https://github.com/organicmaps/organicmaps/issues/10685
622 if (allGlyphs.m_glyphs.empty())
623 LOG(LWARNING, ("No glyphs were found in all fonts for string with characters in warnings above" /*, utf8*/));
624
625 if (m_impl->m_textMetricsCache.size() > kMaxCacheSize)
626 {
627 LOG(LINFO, ("Clearing text metrics cache"));

Callers 3

InitMethod · 0.80
ShapeSingleTextLineMethod · 0.80
RenderGlyphsMethod · 0.80

Calls 14

GetTextSegmentsFunction · 0.85
CountCharFunction · 0.85
NumToHexFunction · 0.85
backMethod · 0.80
findMethod · 0.45
endMethod · 0.45
reserveMethod · 0.45
dataMethod · 0.45
sizeMethod · 0.45
beginMethod · 0.45
ShapeMethod · 0.45
emptyMethod · 0.45

Tested by 1

RenderGlyphsMethod · 0.64