From 6f2878399602f7b1412e5dcf7b4d27778fd7ea6e Mon Sep 17 00:00:00 2001 From: vng Date: Wed, 27 Aug 2014 12:21:05 +0300 Subject: [PATCH] [graphics] Significantly removed memory pressure in StraightTextElement. --- graphics/glyph_layout.cpp | 87 +++++++++++------------------ graphics/glyph_layout.hpp | 89 ++++++++++++++++-------------- graphics/path_text_element.cpp | 24 ++++---- graphics/path_text_element.hpp | 2 +- graphics/straight_text_element.cpp | 62 +++++++++++---------- graphics/straight_text_element.hpp | 7 ++- graphics/text_element.cpp | 70 ++++++++--------------- graphics/text_element.hpp | 23 ++------ 8 files changed, 156 insertions(+), 208 deletions(-) diff --git a/graphics/glyph_layout.cpp b/graphics/glyph_layout.cpp index ef74503375..6fc24773d3 100644 --- a/graphics/glyph_layout.cpp +++ b/graphics/glyph_layout.cpp @@ -7,23 +7,14 @@ namespace graphics { - GlyphLayout::GlyphLayout() - {} - - GlyphLayout::GlyphLayout(GlyphCache * glyphCache, - FontDesc const & fontDesc, - m2::PointD const & pt, - strings::UniString const & visText, - graphics::EPosition pos) + GlyphLayout::GlyphLayout(FontDesc const & font) : m_firstVisible(0), - m_lastVisible(visText.size()), - m_fontDesc(fontDesc), - m_pivot(pt), + m_lastVisible(0), + m_fontDesc(font), + m_pivot(0, 0), m_offset(0, 0), - m_textLength(0), - m_textOffset(0) + m_textLength(0) { - initStraigthText(glyphCache, fontDesc, pt, visText, pos, numeric_limits::max()); } GlyphLayout::GlyphLayout(GlyphCache * glyphCache, @@ -37,27 +28,23 @@ namespace graphics m_fontDesc(fontDesc), m_pivot(pt), m_offset(0, 0), - m_textLength(0), - m_textOffset(0) + m_textLength(0) { initStraigthText(glyphCache, fontDesc, pt, visText, pos, maxWidth); } - GlyphLayout::GlyphLayout(GlyphLayout const & src, - math::Matrix const & m) - : m_firstVisible(0), - m_lastVisible(0), + GlyphLayoutPath::GlyphLayoutPath(GlyphLayoutPath const & src, + math::Matrix const & m) + : GlyphLayout(src.m_fontDesc), m_path(src.m_path, m), - m_visText(src.m_visText), - m_fontDesc(src.m_fontDesc), - m_metrics(src.m_metrics), - m_pivot(0, 0), - m_offset(0, 0), - m_textLength(src.m_textLength) + m_visText(src.m_visText) { if (!m_fontDesc.IsValid()) return; + m_metrics = src.m_metrics; + m_textLength = src.m_textLength; + m_boundRects.push_back(m2::AnyRectD(m2::RectD(0, 0, 0, 0))); m_textOffset = (m2::PointD(0, src.m_textOffset) * m).Length(m2::PointD(0, 0) * m); @@ -69,22 +56,17 @@ namespace graphics recalcAlongPath(); } - GlyphLayout::GlyphLayout(GlyphCache * glyphCache, - FontDesc const & fontDesc, - m2::PointD const * pts, - size_t ptsCount, - strings::UniString const & visText, - double fullLength, - double pathOffset, - double textOffset) - : m_firstVisible(0), - m_lastVisible(0), + GlyphLayoutPath::GlyphLayoutPath(GlyphCache * glyphCache, + FontDesc const & fontDesc, + m2::PointD const * pts, + size_t ptsCount, + strings::UniString const & visText, + double fullLength, + double pathOffset, + double textOffset) + : GlyphLayout(fontDesc), m_path(pts, ptsCount, fullLength, pathOffset), m_visText(visText), - m_fontDesc(fontDesc), - m_pivot(0, 0), - m_offset(0, 0), - m_textLength(0), m_textOffset(textOffset) { if (!m_fontDesc.IsValid()) @@ -224,7 +206,7 @@ namespace graphics m_boundRects.push_back(m2::AnyRectD(boundRect)); } - void GlyphLayout::recalcAlongPath() + void GlyphLayoutPath::recalcAlongPath() { size_t const count = m_visText.size(); if (count == 0 || m_path.fullLength() < m_textLength) @@ -321,7 +303,7 @@ namespace graphics } // storing glyph coordinates relative to pivot point. - for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) + for (size_t i = m_firstVisible; i < m_lastVisible; ++i) m_entries[i].m_pt -= m_pivot; computeBoundRects(); @@ -331,7 +313,7 @@ namespace graphics { map rects; - for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) + for (size_t i = m_firstVisible; i < m_lastVisible; ++i) { if (m_metrics[i].m_width != 0) { @@ -383,16 +365,6 @@ namespace graphics return m_lastVisible; } - buffer_vector const & GlyphLayout::entries() const - { - return m_entries; - } - - buffer_vector const & GlyphLayout::boundRects() const - { - return m_boundRects; - } - m2::PointD const & GlyphLayout::pivot() const { return m_pivot; @@ -400,7 +372,7 @@ namespace graphics void GlyphLayout::setPivot(m2::PointD const & pivot) { - for (unsigned i = 0; i < m_boundRects.size(); ++i) + for (size_t i = 0; i < m_boundRects.size(); ++i) m_boundRects[i].Offset(pivot - m_pivot); m_pivot = pivot; @@ -413,7 +385,7 @@ namespace graphics void GlyphLayout::setOffset(m2::PointD const & offset) { - for (unsigned i = 0; i < m_boundRects.size(); ++i) + for (size_t i = 0; i < m_boundRects.size(); ++i) m_boundRects[i].Offset(offset - m_offset); m_offset = offset; @@ -432,4 +404,9 @@ namespace graphics return -result; } + + bool GlyphLayoutPath::IsFullVisible() const + { + return (m_firstVisible == 0 && m_lastVisible == m_visText.size()); + } } diff --git a/graphics/glyph_layout.hpp b/graphics/glyph_layout.hpp index 45d096e16a..690a8b55f2 100644 --- a/graphics/glyph_layout.hpp +++ b/graphics/glyph_layout.hpp @@ -28,38 +28,29 @@ namespace graphics class GlyphLayout { - private: - + protected: size_t m_firstVisible; size_t m_lastVisible; - TextPath m_path; - - strings::UniString m_visText; - graphics::FontDesc m_fontDesc; - buffer_vector m_metrics; - buffer_vector m_entries; - buffer_vector m_boundRects; + buffer_vector m_metrics; + buffer_vector m_entries; + buffer_vector m_boundRects; m2::PointD m_pivot; m2::PointD m_offset; double m_textLength; - double m_textOffset; void computeBoundRects(); - void recalcPivot(); - void recalcAlongPath(); - - inline void addGlyph(GlyphCache * glyphCache, - GlyphKey const & key, - bool isFirst, - strings::UniChar symbol, - m2::RectD & boundRect, - m2::PointD & curPt); + void addGlyph(GlyphCache * glyphCache, + GlyphKey const & key, + bool isFirst, + strings::UniChar symbol, + m2::RectD & boundRect, + m2::PointD & curPt); void initStraigthText(GlyphCache * glyphCache, FontDesc const & font, @@ -68,40 +59,27 @@ namespace graphics graphics::EPosition pos, unsigned maxWidth); + protected: + GlyphLayout(FontDesc const & font); + public: - - GlyphLayout(); - - GlyphLayout(GlyphLayout const & layout, - math::Matrix const & m); - - GlyphLayout(GlyphCache * glyphCache, - FontDesc const & font, - m2::PointD const & pt, - strings::UniString const & visText, - graphics::EPosition pos); + GlyphLayout() {} GlyphLayout(GlyphCache * glyphCache, FontDesc const & font, m2::PointD const & pt, strings::UniString const & visText, graphics::EPosition pos, - unsigned maxWidth); - - GlyphLayout(GlyphCache * glyphCache, - FontDesc const & font, - m2::PointD const * pts, - size_t ptsCount, - strings::UniString const & visText, - double fullLength, - double pathOffset, - double textOffset); + unsigned maxWidth = numeric_limits::max()); size_t firstVisible() const; size_t lastVisible() const; - buffer_vector const & entries() const; - buffer_vector const & boundRects() const; + buffer_vector const & entries() const { return m_entries; } + buffer_vector const & boundRects() const { return m_boundRects; } + + /// @note! Used only in StraightTextElement. + m2::RectD GetLastGlobalRect() const { return m_boundRects.back().GetGlobalRect(); } graphics::FontDesc const & fontDesc() const; @@ -113,4 +91,31 @@ namespace graphics int baseLineOffset(); }; + + class GlyphLayoutPath : public GlyphLayout + { + TextPath m_path; + strings::UniString m_visText; + + double m_textOffset; + + void recalcAlongPath(); + + public: + GlyphLayoutPath() {} + + GlyphLayoutPath(GlyphLayoutPath const & layout, + math::Matrix const & m); + + GlyphLayoutPath(GlyphCache * glyphCache, + FontDesc const & font, + m2::PointD const * pts, + size_t ptsCount, + strings::UniString const & visText, + double fullLength, + double pathOffset, + double textOffset); + + bool IsFullVisible() const; + }; } diff --git a/graphics/path_text_element.cpp b/graphics/path_text_element.cpp index ad71b30ad7..0a848a82e6 100644 --- a/graphics/path_text_element.cpp +++ b/graphics/path_text_element.cpp @@ -13,18 +13,18 @@ namespace graphics {} PathTextElement::PathTextElement(Params const & p) - : TextElement(p), - m_glyphLayout(p.m_glyphCache, - p.m_fontDesc, - p.m_pts, - p.m_ptsCount, - visText(), - p.m_fullLength, - p.m_pathOffset, - p.m_textOffset) + : TextElement(p) { + strings::UniString visText, auxVisText; + (void) p.GetVisibleTexts(visText, auxVisText); + + m_glyphLayout = GlyphLayoutPath(p.m_glyphCache, p.m_fontDesc, + p.m_pts, p.m_ptsCount, + visText, p.m_fullLength, + p.m_pathOffset, p.m_textOffset); + setPivot(m_glyphLayout.pivot()); - setIsValid((m_glyphLayout.firstVisible() == 0) && (m_glyphLayout.lastVisible() == visText().size())); + setIsValid(m_glyphLayout.IsFullVisible()); } vector const & PathTextElement::boundRects() const @@ -86,9 +86,9 @@ namespace graphics void PathTextElement::setTransformation(const math::Matrix & m) { - m_glyphLayout = GlyphLayout(m_glyphLayout, getResetMatrix() * m); + m_glyphLayout = GlyphLayoutPath(m_glyphLayout, getResetMatrix() * m); TextElement::setPivot(m_glyphLayout.pivot()); - setIsValid((m_glyphLayout.firstVisible() == 0) && (m_glyphLayout.lastVisible() == visText().size())); + setIsValid(m_glyphLayout.IsFullVisible()); TextElement::setTransformation(m); } } diff --git a/graphics/path_text_element.hpp b/graphics/path_text_element.hpp index 67f12144e9..dd601a6eae 100644 --- a/graphics/path_text_element.hpp +++ b/graphics/path_text_element.hpp @@ -10,7 +10,7 @@ namespace graphics { private: - GlyphLayout m_glyphLayout; + GlyphLayoutPath m_glyphLayout; public: diff --git a/graphics/straight_text_element.cpp b/graphics/straight_text_element.cpp index 74bc5afe57..01eff6faa2 100644 --- a/graphics/straight_text_element.cpp +++ b/graphics/straight_text_element.cpp @@ -80,51 +80,54 @@ namespace graphics double allElemWidth = 0; double allElemHeight = 0; - if (!visText().empty()) + strings::UniString visText, auxVisText; + pair const isBidi = p.GetVisibleTexts(visText, auxVisText); + + if (!visText.empty()) { buffer_vector res; - if (p.m_doForceSplit || (p.m_doSplit && !isBidi())) + if (p.m_doForceSplit || (p.m_doSplit && !isBidi.first)) { res.clear(); if (!p.m_delimiters.empty()) - visSplit(visText(), res, p.m_delimiters.c_str(), p.m_useAllParts); + visSplit(visText, res, p.m_delimiters.c_str(), p.m_useAllParts); else - visSplit(visText(), res, " \n\t", p.m_useAllParts); + visSplit(visText, res, " \n\t", p.m_useAllParts); } else - res.push_back(visText()); + res.push_back(visText); - for (unsigned i = 0; i < res.size(); ++i) + for (size_t i = 0; i < res.size(); ++i) { m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_fontDesc, m2::PointD(0, 0), res[i], graphics::EPosCenter, p.m_maxPixelWidth)); - m2::RectD r = m_glyphLayouts.back().boundRects().back().GetGlobalRect(); + m2::RectD const r = m_glyphLayouts.back().GetLastGlobalRect(); allElemWidth = max(r.SizeX(), allElemWidth); allElemHeight += r.SizeY(); } } - if (p.m_auxFontDesc.IsValid() && !auxVisText().empty()) + if (p.m_auxFontDesc.IsValid() && !auxVisText.empty()) { buffer_vector auxRes; - GlyphLayout l(p.m_glyphCache, p.m_auxFontDesc, m2::PointD(0, 0), auxVisText(), graphics::EPosCenter); - if (l.boundRects().back().GetGlobalRect().SizeX() > allElemWidth) + GlyphLayout l(p.m_glyphCache, p.m_auxFontDesc, m2::PointD(0, 0), auxVisText, graphics::EPosCenter); + if (l.GetLastGlobalRect().SizeX() > allElemWidth) { // should split - if (p.m_doSplit && !isAuxBidi()) + if (p.m_doSplit && !isBidi.second) { if (!p.m_delimiters.empty()) - visSplit(auxVisText(), auxRes, p.m_delimiters.c_str(), p.m_useAllParts); + visSplit(auxVisText, auxRes, p.m_delimiters.c_str(), p.m_useAllParts); else - visSplit(auxVisText(), auxRes, " \n\t", p.m_useAllParts); + visSplit(auxVisText, auxRes, " \n\t", p.m_useAllParts); } else - auxRes.push_back(auxVisText()); + auxRes.push_back(auxVisText); } else - auxRes.push_back(auxVisText()); + auxRes.push_back(auxVisText); - for (int i = 0; i < auxRes.size(); ++i) + for (size_t i = 0; i < auxRes.size(); ++i) m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_auxFontDesc, m2::PointD(0, 0), auxRes[i], graphics::EPosCenter)); } @@ -133,32 +136,31 @@ namespace graphics double curShift = allElemHeight / 2; - /// performing aligning of glyphLayouts as for the center position - - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + // performing aligning of glyphLayouts as for the center position + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) { - double elemSize = m_glyphLayouts[i].boundRects().back().GetGlobalRect().SizeY(); + double const elemSize = m_glyphLayouts[i].GetLastGlobalRect().SizeY(); m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, -curShift + elemSize / 2) + p.m_offset); curShift -= elemSize; } if (position() & graphics::EPosLeft) - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(-allElemWidth / 2, 0)); if (position() & graphics::EPosRight) - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(allElemWidth / 2, 0)); if (position() & graphics::EPosAbove) - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, -allElemHeight / 2)); if (position() & graphics::EPosUnder) - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, allElemHeight / 2)); - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) { m_offsets.push_back(m_glyphLayouts[i].pivot()); m_glyphLayouts[i].setPivot(m_offsets[i] + pivot()); @@ -209,7 +211,7 @@ namespace graphics doffs += 1; - for (unsigned i = 0 ; i < boundRects().size(); ++i) + for (size_t i = 0 ; i < boundRects().size(); ++i) screen->drawRectangle(boundRects()[i], c, depth() + doffs); doffs += 1; @@ -218,7 +220,7 @@ namespace graphics if (!isNeedRedraw()) return; - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) { if (m_glyphLayouts[i].fontDesc().m_isMasked) drawTextImpl(m_glyphLayouts[i], screen, m, true, true, m_glyphLayouts[i].fontDesc(), depth() + doffs); @@ -226,7 +228,7 @@ namespace graphics doffs += 1; - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) { graphics::FontDesc fontDesc = m_glyphLayouts[i].fontDesc(); fontDesc.m_isMasked = false; @@ -241,7 +243,7 @@ namespace graphics TextElement::setPivot(pv); - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + offs); } @@ -249,7 +251,7 @@ namespace graphics { setPivot(pivot() * getResetMatrix() * m); - for (unsigned i = 0; i < m_glyphLayouts.size(); ++i) + for (size_t i = 0; i < m_glyphLayouts.size(); ++i) { m_glyphLayouts[i].setPivot(pivot()); m_glyphLayouts[i].setOffset(m_offsets[i]); diff --git a/graphics/straight_text_element.hpp b/graphics/straight_text_element.hpp index 95f6a4100b..ace8709cef 100644 --- a/graphics/straight_text_element.hpp +++ b/graphics/straight_text_element.hpp @@ -10,9 +10,10 @@ namespace graphics { private: - /// glyph layout of the text parts. - vector m_glyphLayouts; - vector m_offsets; + // Glyph layout of the text parts. + // In 99% cases cantainers will hold 1 element. + buffer_vector m_glyphLayouts; + buffer_vector m_offsets; public: diff --git a/graphics/text_element.cpp b/graphics/text_element.cpp index 4963bdb44c..7ee9c8e3cd 100644 --- a/graphics/text_element.cpp +++ b/graphics/text_element.cpp @@ -11,44 +11,30 @@ namespace graphics TextElement::TextElement(Params const & p) : OverlayElement(p), m_fontDesc(p.m_fontDesc), - m_auxFontDesc(p.m_auxFontDesc), - m_logText(p.m_logText), - m_auxLogText(p.m_auxLogText), - m_log2vis(p.m_log2vis) + m_auxFontDesc(p.m_auxFontDesc) + { + } + + pair TextElement::Params::GetVisibleTexts( + strings::UniString & visText, strings::UniString & auxVisText) const { if (m_log2vis) { - m_visText = p.m_glyphCache->log2vis(m_logText); + visText = m_glyphCache->log2vis(m_logText); if (!m_auxLogText.empty()) - m_auxVisText = p.m_glyphCache->log2vis(m_auxLogText); + auxVisText = m_glyphCache->log2vis(m_auxLogText); + + return make_pair(visText != m_logText, auxVisText != m_auxLogText); } else { - m_visText = m_logText; - m_auxVisText = m_auxLogText; + visText = m_logText; + auxVisText = m_auxLogText; + + return make_pair(false, false); } } - strings::UniString const & TextElement::logText() const - { - return m_logText; - } - - strings::UniString const & TextElement::auxLogText() const - { - return m_auxLogText; - } - - strings::UniString const & TextElement::visText() const - { - return m_visText; - } - - strings::UniString const & TextElement::auxVisText() const - { - return m_auxVisText; - } - FontDesc const & TextElement::fontDesc() const { return m_fontDesc; @@ -59,16 +45,6 @@ namespace graphics return m_auxFontDesc; } - bool TextElement::isBidi() const - { - return m_logText != m_visText; - } - - bool TextElement::isAuxBidi() const - { - return m_auxLogText != m_auxVisText; - } - void TextElement::drawTextImpl(GlyphLayout const & layout, OverlayRenderer * screen, math::Matrix const & m, @@ -96,17 +72,17 @@ namespace graphics deltaA = (ang::AngleD(0) * m).val(); } - size_t cnt = layout.entries().size(); + size_t const cnt = layout.entries().size(); buffer_vector glyphInfos(cnt); buffer_vector resInfos(cnt); buffer_vector glyphIDs(cnt); - unsigned firstVis = layout.firstVisible(); - unsigned lastVis = layout.lastVisible(); + size_t const firstVis = layout.firstVisible(); + size_t const lastVis = layout.lastVisible(); /// collecting all glyph infos in one array and packing them as a whole. - for (unsigned i = firstVis; i < lastVis; ++i) + for (size_t i = firstVis; i < lastVis; ++i) { GlyphKey glyphKey(layout.entries()[i].m_sym, fontDesc.m_size, @@ -117,16 +93,16 @@ namespace graphics resInfos[i] = &glyphInfos[i]; } - if ((firstVis != lastVis) - && !screen->mapInfo(&resInfos[firstVis], - &glyphIDs[firstVis], - lastVis - firstVis)) + if (firstVis != lastVis && + !screen->mapInfo(&resInfos[firstVis], + &glyphIDs[firstVis], + lastVis - firstVis)) { LOG(LDEBUG, ("cannot render string", lastVis - firstVis, "characters long")); return; } - for (unsigned i = firstVis; i < lastVis; ++i) + for (size_t i = firstVis; i < lastVis; ++i) { GlyphLayoutElem const & elem = layout.entries()[i]; Glyph const * glyph = static_cast(screen->fromID(glyphIDs[i])); diff --git a/graphics/text_element.hpp b/graphics/text_element.hpp index 279d39018a..6f86581970 100644 --- a/graphics/text_element.hpp +++ b/graphics/text_element.hpp @@ -16,23 +16,10 @@ namespace graphics { protected: - /// text-element specific - FontDesc m_fontDesc; - FontDesc m_auxFontDesc; - - strings::UniString m_logText; //< logical string - strings::UniString m_auxLogText; - - strings::UniString m_visText; //< visual string, BIDI processed - strings::UniString m_auxVisText; - - bool m_log2vis; + FontDesc m_fontDesc, m_auxFontDesc; mutable vector m_boundRects; - bool isBidi() const; - bool isAuxBidi() const; - public: struct Params : OverlayElement::Params @@ -45,6 +32,9 @@ namespace graphics bool m_log2vis; GlyphCache * m_glyphCache; + + pair GetVisibleTexts(strings::UniString & visText, + strings::UniString & auxVisText) const; }; TextElement(Params const & p); @@ -56,10 +46,7 @@ namespace graphics bool doAlignPivot, FontDesc const & desc, double depth) const; - strings::UniString const & logText() const; - strings::UniString const & auxLogText() const; - strings::UniString const & visText() const; - strings::UniString const & auxVisText() const; + FontDesc const & fontDesc() const; FontDesc const & auxFontDesc() const; };