diff --git a/src/components/TextComponent.cpp b/src/components/TextComponent.cpp index dde58662d..08a711f74 100644 --- a/src/components/TextComponent.cpp +++ b/src/components/TextComponent.cpp @@ -82,22 +82,7 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans) if(mTextCache) { const Eigen::Vector2f& textSize = mTextCache->metrics.size; - Eigen::Vector3f off(0, 0, 0); - - switch(mAlignment) - { - case ALIGN_LEFT: - off << 0, (getSize().y() - textSize.y()) / 2, 0; - break; - - case ALIGN_CENTER: - off << (getSize().x() - textSize.x()) / 2, (getSize().y() - textSize.y()) / 2, 0; - break; - - case ALIGN_RIGHT: - off << (getSize().x() - textSize.x()), (getSize().y() - textSize.y()) / 2, 0; - break; - } + Eigen::Vector3f off(0, (getSize().y() - textSize.y()) / 2.0f, 0); if(Settings::getInstance()->getBool("DebugText")) { @@ -112,7 +97,20 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans) // draw the text area, where the text actually is going if(Settings::getInstance()->getBool("DebugText")) - Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), 0x00000033); + { + switch(mAlignment) + { + case ALIGN_LEFT: + Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), 0x00000033); + break; + case ALIGN_CENTER: + Renderer::drawRect((mSize.x() - mTextCache->metrics.size.x()) / 2.0f, 0.0f, mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), 0x00000033); + break; + case ALIGN_RIGHT: + Renderer::drawRect(mSize.x() - mTextCache->metrics.size.x(), 0.0f, mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), 0x00000033); + break; + } + } mFont->renderTextCache(mTextCache.get()); } @@ -140,7 +138,7 @@ void TextComponent::onTextChanged() std::string text = mUppercase ? strToUpper(mText) : mText; std::shared_ptr f = getFont(); - const bool wrap = (mSize.y() == 0 || (int)mSize.y() > f->getHeight()); + const bool wrap = (mSize.y() == 0 || mSize.y() > f->getHeight()*1.2f); Eigen::Vector2f size = f->sizeText(text); if(!wrap && mSize.x() && text.size() && size.x() > mSize.x()) { @@ -156,9 +154,9 @@ void TextComponent::onTextChanged() text.append(abbrev); - mTextCache = std::shared_ptr(f->buildTextCache(text, 0, 0, (mColor >> 8 << 8) | mOpacity)); + mTextCache = std::shared_ptr(f->buildTextCache(text, Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mAlignment)); }else{ - mTextCache = std::shared_ptr(f->buildTextCache(f->wrapText(text, mSize.x()), 0, 0, (mColor >> 8 << 8) | mOpacity)); + mTextCache = std::shared_ptr(f->buildTextCache(f->wrapText(text, mSize.x()), Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mAlignment)); } } diff --git a/src/resources/Font.cpp b/src/resources/Font.cpp index a6cb7ff89..c01641475 100644 --- a/src/resources/Font.cpp +++ b/src/resources/Font.cpp @@ -386,6 +386,27 @@ Eigen::Vector2f Font::getWrappedTextCursorOffset(std::string text, float xLen, i //TextCache //============================================================================================================= +float Font::getNewlineStartOffset(const std::string& text, const unsigned int& charStart, const float& xLen, const Alignment& alignment) +{ + switch(alignment) + { + case ALIGN_LEFT: + return 0; + case ALIGN_CENTER: + { + unsigned int endChar = text.find('\n', charStart); + return (xLen - sizeText(text.substr(charStart, endChar != std::string::npos ? endChar - charStart : endChar)).x()) / 2.0f; + } + case ALIGN_RIGHT: + { + unsigned int endChar = text.find('\n', charStart); + return xLen - (sizeText(text.substr(charStart, endChar != std::string::npos ? endChar - charStart : endChar)).x()); + } + default: + return 0; + } +} + TextCache* Font::buildTextCache(const std::string& text, Eigen::Vector2f offset, unsigned int color, float xLen, Alignment alignment, float lineSpacing) { if(!mTextureID) @@ -394,50 +415,28 @@ TextCache* Font::buildTextCache(const std::string& text, Eigen::Vector2f offset, return NULL; } - // todo - - - - return NULL; -} - -TextCache* Font::buildTextCache(const std::string& text, float offsetX, float offsetY, unsigned int color) -{ - if(!mTextureID) - { - LOG(LogError) << "Error - tried to build TextCache with Font that has no texture loaded!"; - return NULL; - } - - const int triCount = text.length() * 2; - const int vertCount = triCount * 3; + const unsigned int vertCount = text.length() * 2 * 3; // 2 triangles of 3 vertices per character TextCache::Vertex* vert = new TextCache::Vertex[vertCount]; GLubyte* colors = new GLubyte[vertCount * 4]; - // all glyph sizes/texture offsets are in pixels, - // so the only rounding we have to worry about is the offset - offsetX = round(offsetX); - offsetY = round(offsetY); - //texture atlas width/height float tw = (float)mTextureWidth; float th = (float)mTextureHeight; - float x = offsetX; - + float x = offset[0] + (xLen != 0 ? getNewlineStartOffset(text, 0, xLen, alignment) : 0); + float yTop = mCharData['S'].bearingY * mFontScale; - float yBot = getHeight(); - float y = offsetY + (yBot + yTop)/2.0f; + float yBot = getHeight(lineSpacing); + float y = offset[1] + (yBot + yTop)/2.0f; - int charNum = 0; - for(int i = 0; i < vertCount; i += 6, charNum++) + for(unsigned int i = 0, charNum = 0; i < vertCount; i += 6, charNum++) { unsigned char letter = text[charNum]; if(letter == '\n') { - y += (float)getHeight(); - x = offsetX; + y += getHeight(lineSpacing); + x = offset[0] + (xLen != 0 ? getNewlineStartOffset(text, charNum+1, xLen, alignment) : 0); memset(&vert[i], 0, 6 * sizeof(TextCache::Vertex)); continue; } @@ -470,6 +469,13 @@ TextCache* Font::buildTextCache(const std::string& text, float offsetX, float of vert[i + 5].tex[0] = vert[i + 1].tex.x(); vert[i + 5].tex[1] = vert[i + 0].tex.y(); + // round to fix some weird "cut off" text bugs + for(unsigned int j = i; j < i + 6; j++) + { + vert[j].pos[0] = round(vert[j].pos[0]); + vert[j].pos[1] = round(vert[j].pos[1]); + } + x += mCharData[letter].advX * mFontScale; } @@ -481,6 +487,11 @@ TextCache* Font::buildTextCache(const std::string& text, float offsetX, float of return cache; } +TextCache* Font::buildTextCache(const std::string& text, float offsetX, float offsetY, unsigned int color) +{ + return buildTextCache(text, Eigen::Vector2f(offsetX, offsetY), color, 0.0f); +} + TextCache::TextCache(int verts, Vertex* v, GLubyte* c, const CacheMetrics& m) : vertCount(verts), verts(v), colors(c), metrics(m) { } diff --git a/src/resources/Font.h b/src/resources/Font.h index edb68f8db..070322f5d 100644 --- a/src/resources/Font.h +++ b/src/resources/Font.h @@ -99,6 +99,8 @@ private: int mSize; const std::string mPath; + float getNewlineStartOffset(const std::string& text, const unsigned int& charStart, const float& xLen, const Alignment& alignment); + friend TextCache; }; diff --git a/src/views/gamelist/DetailedGameListView.cpp b/src/views/gamelist/DetailedGameListView.cpp index 6aa464c6d..82bbabb93 100644 --- a/src/views/gamelist/DetailedGameListView.cpp +++ b/src/views/gamelist/DetailedGameListView.cpp @@ -107,7 +107,7 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr& them mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE); mDescription.setSize(mDescContainer.getSize().x(), 0); - mDescription.applyTheme(theme, getName(), "md_description", FONT_PATH | FONT_SIZE | COLOR | FORCE_UPPERCASE); + mDescription.applyTheme(theme, getName(), "md_description", FONT_PATH | FONT_SIZE | COLOR | FORCE_UPPERCASE | ALIGNMENT); } void DetailedGameListView::initMDLabels()