forked from organicmaps/organicmaps
added CachedTextView to render texts on GUI thread as a collection of display lists without re-uploading data to texture upon string modification.
This commit is contained in:
parent
2807f21e5f
commit
c9b3cc7ef2
4 changed files with 236 additions and 0 deletions
146
gui/cached_text_view.cpp
Normal file
146
gui/cached_text_view.cpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include "cached_text_view.hpp"
|
||||
#include "controller.hpp"
|
||||
|
||||
#include "../geometry/transformations.hpp"
|
||||
|
||||
#include "../graphics/glyph.hpp"
|
||||
#include "../graphics/screen.hpp"
|
||||
|
||||
namespace gui
|
||||
{
|
||||
CachedTextView::CachedTextView(Params const & p)
|
||||
: Element(p)
|
||||
{
|
||||
m_text = p.m_text;
|
||||
m_uniText = strings::MakeUniString(p.m_text);
|
||||
|
||||
setFont(EActive, graphics::FontDesc(12, graphics::Color(0, 0, 0, 255)));
|
||||
setFont(EPressed, graphics::FontDesc(12, graphics::Color(0, 0, 0, 255)));
|
||||
|
||||
setColor(EActive, graphics::Color(graphics::Color(192, 192, 192, 255)));
|
||||
setColor(EPressed, graphics::Color(graphics::Color(64, 64, 64, 255)));
|
||||
}
|
||||
|
||||
void CachedTextView::setText(string const & text)
|
||||
{
|
||||
if (m_text != text)
|
||||
{
|
||||
m_text = text;
|
||||
m_uniText = strings::MakeUniString(text);
|
||||
setIsDirtyLayout(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CachedTextView::setFont(EState state, graphics::FontDesc const & desc)
|
||||
{
|
||||
setIsDirtyLayout(true);
|
||||
Element::setFont(state, desc);
|
||||
}
|
||||
|
||||
string const & CachedTextView::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
vector<m2::AnyRectD> const & CachedTextView::boundRects() const
|
||||
{
|
||||
if (isDirtyRect())
|
||||
{
|
||||
const_cast<CachedTextView*>(this)->layout();
|
||||
|
||||
m_boundRects.clear();
|
||||
|
||||
copy(m_layout->boundRects().begin(),
|
||||
m_layout->boundRects().end(),
|
||||
back_inserter(m_boundRects));
|
||||
}
|
||||
return m_boundRects;
|
||||
}
|
||||
|
||||
void CachedTextView::draw(graphics::OverlayRenderer *r, math::Matrix<double, 3, 3> const & m) const
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
checkDirtyLayout();
|
||||
|
||||
math::Matrix<double, 3, 3> id = math::Identity<double, 3>();
|
||||
|
||||
if (m_maskedLayout)
|
||||
for (unsigned i = 0; i < m_uniText.size(); ++i)
|
||||
r->drawDisplayList(m_maskedDls[i].get(),
|
||||
math::Shift(id, m_maskedLayout->entries()[i].m_pt + m_maskedLayout->pivot()));
|
||||
|
||||
for (unsigned i = 0; i < m_uniText.size(); ++i)
|
||||
r->drawDisplayList(m_dls[i].get(),
|
||||
math::Shift(id, m_layout->entries()[i].m_pt + m_layout->pivot()));
|
||||
}
|
||||
}
|
||||
|
||||
void CachedTextView::cache()
|
||||
{
|
||||
layout();
|
||||
|
||||
DisplayListCache * dlc = m_controller->GetDisplayListCache();
|
||||
graphics::FontDesc fontDesc = font(EActive);
|
||||
|
||||
if (fontDesc.m_isMasked)
|
||||
{
|
||||
m_maskedDls.resize(m_uniText.size());
|
||||
for (unsigned i = 0; i < m_uniText.size(); ++i)
|
||||
m_maskedDls[i] = dlc->FindGlyph(graphics::GlyphKey(m_uniText[i],
|
||||
fontDesc.m_size,
|
||||
fontDesc.m_isMasked,
|
||||
fontDesc.m_isMasked ? fontDesc.m_maskColor : fontDesc.m_color));
|
||||
|
||||
fontDesc.m_isMasked = false;
|
||||
}
|
||||
|
||||
m_dls.resize(m_uniText.size());
|
||||
|
||||
for (unsigned i = 0; i < m_uniText.size(); ++i)
|
||||
m_dls[i] = dlc->FindGlyph(graphics::GlyphKey(m_uniText[i],
|
||||
fontDesc.m_size,
|
||||
fontDesc.m_isMasked,
|
||||
fontDesc.m_color));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CachedTextView::purge()
|
||||
{
|
||||
m_dls.clear();
|
||||
}
|
||||
|
||||
void CachedTextView::layout()
|
||||
{
|
||||
if (m_uniText.empty())
|
||||
return;
|
||||
|
||||
graphics::FontDesc fontDesc = font(EActive);
|
||||
|
||||
if (fontDesc.m_isMasked)
|
||||
{
|
||||
m_maskedLayout.reset(new graphics::GlyphLayout(m_controller->GetGlyphCache(),
|
||||
fontDesc,
|
||||
pivot(),
|
||||
m_uniText,
|
||||
position()));
|
||||
fontDesc.m_isMasked = false;
|
||||
}
|
||||
|
||||
m_layout.reset(new graphics::GlyphLayout(m_controller->GetGlyphCache(),
|
||||
fontDesc,
|
||||
pivot(),
|
||||
m_uniText,
|
||||
position()));
|
||||
}
|
||||
|
||||
void CachedTextView::setPivot(m2::PointD const & pv)
|
||||
{
|
||||
Element::setPivot(pv);
|
||||
if (m_maskedLayout)
|
||||
m_maskedLayout->setPivot(pivot());
|
||||
if (m_layout)
|
||||
m_layout->setPivot(pivot());
|
||||
}
|
||||
}
|
57
gui/cached_text_view.hpp
Normal file
57
gui/cached_text_view.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "element.hpp"
|
||||
|
||||
#include "../std/map.hpp"
|
||||
#include "../std/vector.hpp"
|
||||
#include "../std/shared_ptr.hpp"
|
||||
|
||||
#include "../base/string_utils.hpp"
|
||||
#include "../base/matrix.hpp"
|
||||
|
||||
#include "../graphics/glyph_cache.hpp"
|
||||
#include "../graphics/display_list.hpp"
|
||||
#include "../graphics/glyph_layout.hpp"
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class CachedTextView : public Element
|
||||
{
|
||||
private:
|
||||
|
||||
string m_text;
|
||||
|
||||
strings::UniString m_uniText;
|
||||
|
||||
vector<shared_ptr<graphics::DisplayList> > m_dls;
|
||||
vector<shared_ptr<graphics::DisplayList> > m_maskedDls;
|
||||
|
||||
scoped_ptr<graphics::GlyphLayout> m_layout;
|
||||
scoped_ptr<graphics::GlyphLayout> m_maskedLayout;
|
||||
|
||||
mutable vector<m2::AnyRectD> m_boundRects;
|
||||
|
||||
public:
|
||||
|
||||
struct Params : public Element::Params
|
||||
{
|
||||
string m_text;
|
||||
};
|
||||
|
||||
CachedTextView(Params const & p);
|
||||
|
||||
void setText(string const & text);
|
||||
string const & text() const;
|
||||
|
||||
vector<m2::AnyRectD> const & boundRects() const;
|
||||
void draw(graphics::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
|
||||
|
||||
void cache();
|
||||
void purge();
|
||||
void layout();
|
||||
|
||||
void setFont(EState state, graphics::FontDesc const & desc);
|
||||
|
||||
void setPivot(m2::PointD const & pv);
|
||||
};
|
||||
}
|
|
@ -16,6 +16,8 @@ HEADERS += \
|
|||
text_view.hpp \
|
||||
balloon.hpp \
|
||||
image_view.hpp \
|
||||
cached_text_view.hpp \
|
||||
display_list_cache.hpp
|
||||
|
||||
SOURCES += \
|
||||
controller.cpp \
|
||||
|
@ -24,3 +26,5 @@ SOURCES += \
|
|||
text_view.cpp \
|
||||
balloon.cpp \
|
||||
image_view.cpp \
|
||||
cached_text_view.cpp \
|
||||
display_list_cache.cpp
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../button.hpp"
|
||||
#include "../text_view.hpp"
|
||||
#include "../image_view.hpp"
|
||||
#include "../cached_text_view.hpp"
|
||||
|
||||
struct BalloonTest
|
||||
{
|
||||
|
@ -117,6 +118,33 @@ struct TextViewTest
|
|||
}
|
||||
};
|
||||
|
||||
struct CachedTextViewTest
|
||||
{
|
||||
shared_ptr<gui::CachedTextView> m_cachedTextView;
|
||||
|
||||
void Init(gui::Controller * c)
|
||||
{
|
||||
gui::CachedTextView::Params ctp;
|
||||
|
||||
ctp.m_pivot = m2::PointD(100, 100);
|
||||
ctp.m_depth = graphics::maxDepth;
|
||||
ctp.m_position = graphics::EPosAbove;
|
||||
ctp.m_text = "(123.15, 783.123)";
|
||||
|
||||
m_cachedTextView.reset(new gui::CachedTextView(ctp));
|
||||
m_cachedTextView->setIsVisible(true);
|
||||
|
||||
m_cachedTextView->setFont(gui::Element::EActive,
|
||||
graphics::FontDesc(20, graphics::Color(0, 0, 0, 255), true));
|
||||
|
||||
c->AddElement(m_cachedTextView);
|
||||
}
|
||||
|
||||
void DoDraw(shared_ptr<graphics::Screen> const & p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct ImageViewTest
|
||||
{
|
||||
shared_ptr<gui::ImageView> m_imageView;
|
||||
|
@ -155,4 +183,5 @@ UNIT_TEST_GUI(BalloonTest);
|
|||
UNIT_TEST_GUI(ButtonTest);
|
||||
UNIT_TEST_GUI(TextViewTest);
|
||||
UNIT_TEST_GUI(ImageViewTest);
|
||||
UNIT_TEST_GUI(CachedTextViewTest);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue