Optimize UITextEdit rendering
This commit is contained in:
parent
559e545e36
commit
6893a5e98a
|
@ -135,6 +135,12 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PainterOGL1::drawFillCoords(CoordsBuffer& coordsBuffer)
|
||||||
|
{
|
||||||
|
setTexture(nullptr);
|
||||||
|
drawCoords(coordsBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
||||||
{
|
{
|
||||||
if(texture->isEmpty())
|
if(texture->isEmpty())
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
void refreshState();
|
void refreshState();
|
||||||
|
|
||||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||||
|
void drawFillCoords(CoordsBuffer& coordsBuffer);
|
||||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||||
|
|
|
@ -120,6 +120,13 @@ void PainterOGL2::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
|
||||||
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
|
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PainterOGL2::drawFillCoords(CoordsBuffer& coordsBuffer)
|
||||||
|
{
|
||||||
|
setDrawProgram(m_shaderProgram ? m_shaderProgram : m_drawSolidColorProgram.get());
|
||||||
|
setTexture(nullptr);
|
||||||
|
drawCoords(coordsBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
||||||
{
|
{
|
||||||
if(texture && texture->isEmpty())
|
if(texture && texture->isEmpty())
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
||||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||||
|
void drawFillCoords(CoordsBuffer& coordsBuffer);
|
||||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
virtual void clear(const Color& color) = 0;
|
virtual void clear(const Color& color) = 0;
|
||||||
|
|
||||||
virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
|
virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
|
||||||
|
virtual void drawFillCoords(CoordsBuffer& coordsBuffer) = 0;
|
||||||
virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
|
virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
|
||||||
virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
||||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
|
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
|
||||||
|
|
|
@ -49,6 +49,9 @@ UITextEdit::UITextEdit()
|
||||||
m_updatesEnabled = true;
|
m_updatesEnabled = true;
|
||||||
m_selectionColor = Color::white;
|
m_selectionColor = Color::white;
|
||||||
m_selectionBackgroundColor = Color::black;
|
m_selectionBackgroundColor = Color::black;
|
||||||
|
m_glyphsTextCoordsBuffer.enableHardwareCaching();
|
||||||
|
m_glyphsSelectCoordsBuffer.enableHardwareCaching();
|
||||||
|
m_glyphsMustRecache = true;
|
||||||
blinkCursor();
|
blinkCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,38 +65,36 @@ void UITextEdit::drawSelf(Fw::DrawPane drawPane)
|
||||||
drawImage(m_rect);
|
drawImage(m_rect);
|
||||||
drawIcon(m_rect);
|
drawIcon(m_rect);
|
||||||
|
|
||||||
//TODO: text rendering could be much optimized by using vertex buffer or caching the render into a texture
|
|
||||||
|
|
||||||
int textLength = m_text.length();
|
int textLength = m_text.length();
|
||||||
const TexturePtr& texture = m_font->getTexture();
|
const TexturePtr& texture = m_font->getTexture();
|
||||||
if(!texture)
|
if(!texture)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(hasSelection()) {
|
bool glyphsMustRecache = m_glyphsMustRecache;
|
||||||
if(m_color != Color::alpha) {
|
if(glyphsMustRecache)
|
||||||
g_painter->setColor(m_color);
|
m_glyphsMustRecache = false;
|
||||||
for(int i=0;i<m_selectionStart;++i)
|
|
||||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=m_selectionStart;i<m_selectionEnd;++i) {
|
if(m_color != Color::alpha) {
|
||||||
g_painter->setColor(m_selectionBackgroundColor);
|
if(glyphsMustRecache) {
|
||||||
g_painter->drawFilledRect(m_glyphsCoords[i]);
|
m_glyphsTextCoordsBuffer.clear();
|
||||||
g_painter->setColor(m_selectionColor);
|
for(int i=0;i<textLength;++i)
|
||||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
m_glyphsTextCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_color != Color::alpha) {
|
|
||||||
g_painter->setColor(m_color);
|
|
||||||
for(int i=m_selectionEnd;i<textLength;++i)
|
|
||||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
|
||||||
}
|
|
||||||
} else if(m_color != Color::alpha) {
|
|
||||||
g_painter->setColor(m_color);
|
g_painter->setColor(m_color);
|
||||||
for(int i=0;i<textLength;++i)
|
g_painter->drawTextureCoords(m_glyphsTextCoordsBuffer, texture);
|
||||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hasSelection()) {
|
||||||
|
if(glyphsMustRecache) {
|
||||||
|
m_glyphsSelectCoordsBuffer.clear();
|
||||||
|
for(int i=m_selectionStart;i<m_selectionEnd;++i)
|
||||||
|
m_glyphsSelectCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
|
||||||
|
}
|
||||||
|
g_painter->setColor(m_selectionBackgroundColor);
|
||||||
|
g_painter->drawFillCoords(m_glyphsSelectCoordsBuffer);
|
||||||
|
g_painter->setColor(m_selectionColor);
|
||||||
|
g_painter->drawTextureCoords(m_glyphsSelectCoordsBuffer, texture);
|
||||||
|
}
|
||||||
|
|
||||||
// render cursor
|
// render cursor
|
||||||
if(isExplicitlyEnabled() && m_cursorVisible && m_cursorInRange && isActive() && m_cursorPos >= 0) {
|
if(isExplicitlyEnabled() && m_cursorVisible && m_cursorInRange && isActive() && m_cursorPos >= 0) {
|
||||||
|
@ -136,6 +137,9 @@ void UITextEdit::update(bool focusCursor)
|
||||||
if(m_rect.isEmpty())
|
if(m_rect.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// recache coords buffers
|
||||||
|
recacheGlyphs();
|
||||||
|
|
||||||
// map glyphs positions
|
// map glyphs positions
|
||||||
Size textBoxSize;
|
Size textBoxSize;
|
||||||
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize);
|
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize);
|
||||||
|
@ -360,6 +364,7 @@ void UITextEdit::setSelection(int start, int end)
|
||||||
|
|
||||||
m_selectionStart = stdext::clamp<int>(start, 0, (int)m_text.length());
|
m_selectionStart = stdext::clamp<int>(start, 0, (int)m_text.length());
|
||||||
m_selectionEnd = stdext::clamp<int>(end, 0, (int)m_text.length());
|
m_selectionEnd = stdext::clamp<int>(end, 0, (int)m_text.length());
|
||||||
|
recacheGlyphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITextEdit::setTextHidden(bool hidden)
|
void UITextEdit::setTextHidden(bool hidden)
|
||||||
|
|
|
@ -108,6 +108,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void disableUpdates() { m_updatesEnabled = false; }
|
void disableUpdates() { m_updatesEnabled = false; }
|
||||||
void enableUpdates() { m_updatesEnabled = true; }
|
void enableUpdates() { m_updatesEnabled = true; }
|
||||||
|
void recacheGlyphs() { m_glyphsMustRecache = true; }
|
||||||
|
|
||||||
Rect m_drawArea;
|
Rect m_drawArea;
|
||||||
int m_cursorPos;
|
int m_cursorPos;
|
||||||
|
@ -137,6 +138,10 @@ private:
|
||||||
|
|
||||||
std::vector<Rect> m_glyphsCoords;
|
std::vector<Rect> m_glyphsCoords;
|
||||||
std::vector<Rect> m_glyphsTexCoords;
|
std::vector<Rect> m_glyphsTexCoords;
|
||||||
|
|
||||||
|
CoordsBuffer m_glyphsTextCoordsBuffer;
|
||||||
|
CoordsBuffer m_glyphsSelectCoordsBuffer;
|
||||||
|
bool m_glyphsMustRecache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue