From 26badc56e02fcc1b8aa53f24e91af5fa37b88f4d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 16 May 2013 16:10:38 -0700 Subject: [PATCH] Added shadow and outline effects to TextRenderer, use the shadow effect in our text to separate it from the background. --- interface/src/Avatar.cpp | 4 +++- interface/src/Log.cpp | 2 +- interface/src/Util.cpp | 2 +- interface/src/ui/TextRenderer.cpp | 32 ++++++++++++++++++++++++++++--- interface/src/ui/TextRenderer.h | 11 ++++++++++- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 03c803b798..eda3247cd5 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -753,7 +753,7 @@ void Avatar::setDisplayingHead(bool displayingHead) { } static TextRenderer* textRenderer() { - static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24); + static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); return renderer; } @@ -833,6 +833,7 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { glScalef(chatMessageScale, chatMessageScale, 1.0f); glDisable(GL_LIGHTING); + glDepthMask(false); if (_keyState == NO_KEY_DOWN) { textRenderer()->draw(-width/2, 0, _chatMessage.c_str()); @@ -848,6 +849,7 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { textRenderer()->draw(width/2 - lastWidth, 0, _chatMessage.c_str() + lastIndex); } glEnable(GL_LIGHTING); + glDepthMask(true); glPopMatrix(); } diff --git a/interface/src/Log.cpp b/interface/src/Log.cpp index 5fcfb51e25..9b57df1694 100644 --- a/interface/src/Log.cpp +++ b/interface/src/Log.cpp @@ -198,7 +198,7 @@ void Log::setCharacterSize(unsigned width, unsigned height) { } static TextRenderer* textRenderer() { - static TextRenderer* renderer = new TextRenderer(FONT_FAMILY); + static TextRenderer* renderer = new TextRenderer(FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT); return renderer; } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index bf3c568012..2df1196a86 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -181,7 +181,7 @@ double diffclock(timeval *clock1,timeval *clock2) static TextRenderer* textRenderer(int mono) { static TextRenderer* monoRenderer = new TextRenderer(MONO_FONT_FAMILY); - static TextRenderer* proportionalRenderer = new TextRenderer(SANS_FONT_FAMILY); + static TextRenderer* proportionalRenderer = new TextRenderer(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT); return mono ? monoRenderer : proportionalRenderer; } diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index 3130463398..df04988bc9 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -19,9 +19,10 @@ Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int wid _textureID(textureID), _location(location), _bounds(bounds), _width(width) { } -TextRenderer::TextRenderer(const char* family, int pointSize, int weight, bool italic) - : _font(family, pointSize, weight, italic), - _metrics(_font), _x(IMAGE_SIZE), _y(IMAGE_SIZE), _rowHeight(0) { +TextRenderer::TextRenderer(const char* family, int pointSize, int weight, + bool italic, EffectType effectType, int effectThickness) + : _font(family, pointSize, weight, italic), _metrics(_font), _effectType(effectType), + _effectThickness(effectThickness), _x(IMAGE_SIZE), _y(IMAGE_SIZE), _rowHeight(0) { _font.setKerning(false); } @@ -97,6 +98,14 @@ const Glyph& TextRenderer::getGlyph(char c) { glyph = Glyph(0, QPoint(), QRect(), _metrics.width(ch)); return glyph; } + // grow the bounds to account for effect, if any + if (_effectType == SHADOW_EFFECT) { + bounds.adjust(-_effectThickness, 0, 0, _effectThickness); + + } else if (_effectType == OUTLINE_EFFECT) { + bounds.adjust(-_effectThickness, -_effectThickness, _effectThickness, _effectThickness); + } + // grow the bounds to account for antialiasing bounds.adjust(-1, -1, 1, 1); @@ -128,6 +137,23 @@ const Glyph& TextRenderer::getGlyph(char c) { image.fill(0); QPainter painter(&image); painter.setFont(_font); + if (_effectType == SHADOW_EFFECT) { + for (int i = 0; i < _effectThickness; i++) { + painter.drawText(-bounds.x() - i, -bounds.y() + i, ch); + } + } else if (_effectType == OUTLINE_EFFECT) { + QPainterPath path; + QFont font = _font; + font.setStyleStrategy(QFont::ForceOutline); + path.addText(-bounds.x() - 0.5, -bounds.y() + 0.5, font, ch); + QPen pen; + pen.setWidth(_effectThickness); + pen.setJoinStyle(Qt::RoundJoin); + pen.setCapStyle(Qt::RoundCap); + painter.setPen(pen); + painter.setRenderHint(QPainter::Antialiasing); + painter.drawPath(path); + } painter.setPen(QColor(255, 255, 255)); painter.drawText(-bounds.x(), -bounds.y(), ch); } diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index 6de0c77bad..6df7186d86 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -23,7 +23,10 @@ class Glyph; class TextRenderer { public: - TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false); + enum EffectType { NO_EFFECT, SHADOW_EFFECT, OUTLINE_EFFECT }; + + TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false, + EffectType effect = NO_EFFECT, int effectThickness = 2); ~TextRenderer(); const QFontMetrics& metrics() const { return _metrics; } @@ -42,6 +45,12 @@ private: // the font metrics QFontMetrics _metrics; + + // the type of effect to apply + EffectType _effectType; + + // the thickness of the effect + int _effectThickness; // maps characters to cached glyph info QHash _glyphs;