From 0a959f13b7cefee9c5858a2a1bf093e9bbfbf96e Mon Sep 17 00:00:00 2001 From: rachytski Date: Mon, 7 Feb 2011 02:56:56 +0200 Subject: [PATCH] drawing texts without clipping them on frame borders. --- map/render_queue_routine.cpp | 22 +++++++++--- yg/text_renderer.cpp | 68 ++++++++++++++++++++++++++++++++---- yg/text_renderer.hpp | 24 +++++++++++-- 3 files changed, 101 insertions(+), 13 deletions(-) diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 9040af9155..1c9ecb8f62 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -220,6 +220,7 @@ void RenderQueueRoutine::Do() params.m_frameBuffer = m_frameBuffer; params.m_renderState = m_renderState; params.m_doPeriodicalUpdate = m_doPeriodicalUpdate; + params.m_textTreeAutoClean = false; m_threadDrawer = make_shared_ptr(new DrawerYG(m_skinName, params)); @@ -287,17 +288,29 @@ void RenderQueueRoutine::Do() m_threadDrawer->screen()->setClipRect(m2::RectI(0, 0, s.m_textureWidth, s.m_textureHeight)); m_threadDrawer->clear(); -// m_threadDrawer->screen()->setClipRect(m2::RectI(0, 0, s.m_surfaceWidth, s.m_surfaceHeight)); - if (s.isPanning()) + { m_threadDrawer->screen()->blit( s.m_actualTarget, s.m_actualScreen, s.m_currentScreen); + m2::RectD curRect(0, 0, s.m_textureWidth, s.m_textureHeight); + m2::RectD oldRect(s.m_currentScreen.GtoP(s.m_actualScreen.PtoG(m2::PointD(0, 0))), + s.m_currentScreen.GtoP(s.m_actualScreen.PtoG(m2::PointD(s.m_textureWidth, s.m_textureHeight)))); + + if (!curRect.Intersect(oldRect)) + curRect = m2::RectD(0, 0, 0, 0); + + m_threadDrawer->screen()->offsetTextTree( + s.m_currentScreen.GtoP(s.m_actualScreen.PtoG(m2::PointD(0, 0))), + curRect); + } + else + m_threadDrawer->screen()->clearTextTree(); + ScreenBase const & frameScreen = m_currentRenderCommand->m_frameScreen; m2::RectD glbRect; -// frameScreen.PtoG(m2::RectD(0, 0, m_renderState->m_surfaceWidth, m_renderState->m_surfaceHeight), glbRect); frameScreen.PtoG(m2::RectD(0, 0, s.m_surfaceWidth, s.m_surfaceHeight), glbRect); int scaleLevel = scales::GetScaleLevel(glbRect); @@ -306,7 +319,6 @@ void RenderQueueRoutine::Do() if ((areas[i].SizeX() != 0) && (areas[i].SizeY() != 0)) { frameScreen.PtoG(m2::Inflate(m2::RectD(areas[i]), 30 * m_visualScale, 30 * m_visualScale), glbRect); -// frameScreen.PtoG(m2::Inflate(m2::RectD(areas[i]), (double)200, (double)200), glbRect); if ((glbRect.SizeX() == 0) || (glbRect.SizeY() == 0)) continue; @@ -320,6 +332,8 @@ void RenderQueueRoutine::Do() } } + /// setting the "whole texture" clip rect to render texts opened by panning. + m_threadDrawer->screen()->setClipRect(m2::RectI(0, 0, s.m_textureWidth, s.m_textureHeight)); m_threadDrawer->endFrame(); } diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index 7d568b8a07..1e15844517 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -22,13 +22,26 @@ namespace yg { namespace gl { - TextRenderer::TextRenderer(base_t::Params const & params) - : base_t(params) + TextRenderer::Params::Params() + : m_textTreeAutoClean(true) + {} + + TextRenderer::TextRenderer(Params const & params) + : base_t(params), m_textTreeAutoClean(params.m_textTreeAutoClean) {} void TextRenderer::TextObj::Draw(TextRenderer * pTextRenderer) const { - pTextRenderer->drawTextImpl(m_pt, 0.0, m_size, m_color, m_utf8Text, m_isMasked, m_maskColor, yg::maxDepth, m_isFixedFont, m_log2vis); + /// this value is assigned inside offsetTextRect function to the texts which completely + /// lies inside the testing rect and therefore should be skipped. + if (m_needRedraw) + { + pTextRenderer->drawTextImpl(m_pt, 0.0, m_size, m_color, m_utf8Text, m_isMasked, m_maskColor, yg::maxDepth, m_isFixedFont, m_log2vis); + /// boosting its depth to "out of range" value, + /// to mark it as a rendered text and prevent it from + /// popping out of tree, when more important text arrives + m_depth = yg::maxDepth; + } } m2::RectD const TextRenderer::TextObj::GetLimitRect(TextRenderer* pTextRenderer) const @@ -36,6 +49,17 @@ namespace yg return m2::Offset(pTextRenderer->textRect(m_utf8Text, m_size, false, m_log2vis), m_pt); } + void TextRenderer::TextObj::SetNeedRedraw(bool flag) const + { + m_needRedraw = flag; + } + + void TextRenderer::TextObj::Offset(m2::PointD const & offs) + { + m_pt += offs; + } + + void TextRenderer::drawText(m2::PointD const & pt, float angle, uint8_t fontSize, @@ -59,19 +83,51 @@ namespace yg void TextRenderer::setClipRect(m2::RectI const & rect) { - m_tree.ForEach(bind(&TextObj::Draw, _1, this)); - m_tree.Clear(); +// m_tree.ForEach(bind(&TextObj::Draw, _1, this)); +// m_tree.ForEach(bind(&TextObj::BoostPriority, _1)); +// if (m_textTreeAutoClean) +// m_tree.Clear(); base_t::setClipRect(rect); } void TextRenderer::endFrame() { m_tree.ForEach(bind(&TextObj::Draw, _1, this)); - m_tree.Clear(); + if (m_textTreeAutoClean) + m_tree.Clear(); base_t::endFrame(); } + void TextRenderer::clearTextTree() + { + m_tree.Clear(); + } + + void TextRenderer::offsetTextTree(m2::PointD const & offs, m2::RectD const & rect) + { + vector texts; + m_tree.ForEach(bind(&vector::push_back, ref(texts), _1)); + m_tree.Clear(); + for (vector::iterator it = texts.begin(); it != texts.end(); ++it) + { + it->Offset(offs); + + m2::RectD limitRect = it->GetLimitRect(this); + + /// fully inside shouldn't be rendered + if (rect.IsRectInside(limitRect)) + it->SetNeedRedraw(false); + else + /// intersecting the borders, should be re-rendered + if (rect.IsIntersect(limitRect)) + it->SetNeedRedraw(true); + + if (limitRect.IsIntersect(rect)) + m_tree.Add(*it, limitRect); + } + } + template void TextRenderer::ForEachGlyph(uint8_t fontSize, yg::Color const & color, wstring const & text, bool isMasked, bool isFixedFont, ToDo toDo) { diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index d0554eb687..fe5a443fee 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -27,20 +27,24 @@ namespace yg uint8_t m_size; string m_utf8Text; bool m_isMasked; - double m_depth; + mutable double m_depth; + mutable bool m_needRedraw; bool m_isFixedFont; bool m_log2vis; yg::Color m_color; yg::Color m_maskColor; public: + TextObj(m2::PointD const & pt, string const & txt, uint8_t sz, yg::Color const & c, bool isMasked, yg::Color const & maskColor, double d, bool isFixedFont, bool log2vis) - : m_pt(pt), m_size(sz), m_utf8Text(txt), m_isMasked(isMasked), m_depth(d), m_isFixedFont(isFixedFont), m_log2vis(log2vis), m_color(c), m_maskColor(maskColor) + : m_pt(pt), m_size(sz), m_utf8Text(txt), m_isMasked(isMasked), m_depth(d), m_needRedraw(true), m_isFixedFont(isFixedFont), m_log2vis(log2vis), m_color(c), m_maskColor(maskColor) { } void Draw(TextRenderer * pTextRenderer) const; m2::RectD const GetLimitRect(TextRenderer * pTextRenderer) const; + void SetNeedRedraw(bool needRedraw) const; + void Offset(m2::PointD const & pt); struct better_depth { @@ -90,12 +94,19 @@ namespace yg bool fixedFont, bool log2vis); + bool m_textTreeAutoClean; public: typedef PathRenderer base_t; - TextRenderer(base_t::Params const & params); + struct Params : base_t::Params + { + bool m_textTreeAutoClean; + Params(); + }; + + TextRenderer(Params const & params); /// Drawing text from point rotated by the angle. void drawText(m2::PointD const & pt, @@ -132,6 +143,13 @@ namespace yg void setClipRect(m2::RectI const & rect); void endFrame(); + + void clearTextTree(); + /// shift all elements in the tree by the specified offset + /// leaving only those elements, which intersect the specified rect + /// boosting their priority to the top for them not to be filtered away, + /// when the new texts arrive + void offsetTextTree(m2::PointD const & offs, m2::RectD const & r); }; } }