From 5099593d730f0325534280c5ec17d97f73cffb46 Mon Sep 17 00:00:00 2001
From: Leon Styhre <leon@leonstyhre.com>
Date: Sat, 13 Mar 2021 16:52:15 +0100
Subject: [PATCH] The gamelist description text no longer scrolls above the
 starting position.

---
 .../views/gamelist/DetailedGameListView.cpp   |  1 +
 .../src/views/gamelist/VideoGameListView.cpp  |  1 +
 es-core/src/components/TextComponent.cpp      | 13 ++++++++--
 es-core/src/components/TextComponent.h        |  2 ++
 es-core/src/resources/Font.cpp                | 24 ++++++++++++++-----
 es-core/src/resources/Font.h                  | 12 +++++++---
 themes/rbsimple-DE/theme.xml                  |  2 +-
 7 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/es-app/src/views/gamelist/DetailedGameListView.cpp b/es-app/src/views/gamelist/DetailedGameListView.cpp
index fa979b29d..323ca8730 100644
--- a/es-app/src/views/gamelist/DetailedGameListView.cpp
+++ b/es-app/src/views/gamelist/DetailedGameListView.cpp
@@ -122,6 +122,7 @@ DetailedGameListView::DetailedGameListView(
 
     mDescription.setFont(Font::get(FONT_SIZE_SMALL));
     mDescription.setSize(mDescContainer.getSize().x(), 0);
+    mDescription.setNoTopMargin(true);
     mDescContainer.addChild(&mDescription);
 
     mGamelistInfo.setOrigin(0.5f, 0.5f);
diff --git a/es-app/src/views/gamelist/VideoGameListView.cpp b/es-app/src/views/gamelist/VideoGameListView.cpp
index b91404f23..a951f27d7 100644
--- a/es-app/src/views/gamelist/VideoGameListView.cpp
+++ b/es-app/src/views/gamelist/VideoGameListView.cpp
@@ -140,6 +140,7 @@ VideoGameListView::VideoGameListView(
 
     mDescription.setFont(Font::get(FONT_SIZE_SMALL));
     mDescription.setSize(mDescContainer.getSize().x(), 0);
+    mDescription.setNoTopMargin(true);
     mDescContainer.addChild(&mDescription);
 
     mGamelistInfo.setOrigin(0.5f, 0.5f);
diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp
index 62302b61e..d4f9b0605 100644
--- a/es-core/src/components/TextComponent.cpp
+++ b/es-core/src/components/TextComponent.cpp
@@ -22,6 +22,7 @@ TextComponent::TextComponent(
         mHorizontalAlignment(ALIGN_LEFT),
         mVerticalAlignment(ALIGN_CENTER),
         mLineSpacing(1.5f),
+        mNoTopMargin(false),
         mBgColor(0),
         mMargin(0.0f),
         mRenderBackground(false)
@@ -46,6 +47,7 @@ TextComponent::TextComponent(
         mHorizontalAlignment(align),
         mVerticalAlignment(ALIGN_CENTER),
         mLineSpacing(1.5f),
+        mNoTopMargin(false),
         mBgColor(0),
         mMargin(margin),
         mRenderBackground(false)
@@ -245,12 +247,13 @@ void TextComponent::onTextChanged()
         text.append(abbrev);
 
         mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(text, Vector2f(0, 0),
-                (mColor >> 8 << 8) | mOpacity, mSize.x(), mHorizontalAlignment, mLineSpacing));
+                (mColor >> 8 << 8) | mOpacity, mSize.x(), mHorizontalAlignment,
+                mLineSpacing, mNoTopMargin));
     }
     else {
         mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(f->wrapText(
                 text, mSize.x()), Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(),
-                        mHorizontalAlignment, mLineSpacing));
+                        mHorizontalAlignment, mLineSpacing, mNoTopMargin));
     }
 }
 
@@ -277,6 +280,12 @@ void TextComponent::setLineSpacing(float spacing)
     onTextChanged();
 }
 
+void TextComponent::setNoTopMargin(bool margin)
+{
+    mNoTopMargin = margin;
+    onTextChanged();
+}
+
 std::string TextComponent::getValue() const
 {
     return mText;
diff --git a/es-core/src/components/TextComponent.h b/es-core/src/components/TextComponent.h
index a6c55d380..d1f2438b2 100644
--- a/es-core/src/components/TextComponent.h
+++ b/es-core/src/components/TextComponent.h
@@ -45,6 +45,7 @@ public:
     void setHorizontalAlignment(Alignment align);
     void setVerticalAlignment(Alignment align);
     void setLineSpacing(float spacing);
+    void setNoTopMargin(bool margin);
     void setBackgroundColor(unsigned int color);
     void setRenderBackground(bool render);
 
@@ -90,6 +91,7 @@ private:
     Alignment mHorizontalAlignment;
     Alignment mVerticalAlignment;
     float mLineSpacing;
+    bool mNoTopMargin;
 };
 
 #endif // ES_CORE_COMPONENTS_TEXT_COMPONENT_H
diff --git a/es-core/src/resources/Font.cpp b/es-core/src/resources/Font.cpp
index 108ae975f..8f3cde2e8 100644
--- a/es-core/src/resources/Font.cpp
+++ b/es-core/src/resources/Font.cpp
@@ -574,13 +574,23 @@ TextCache* Font::buildTextCache(
         unsigned int color,
         float xLen,
         Alignment alignment,
-        float lineSpacing)
+        float lineSpacing,
+        bool noTopMargin)
 {
     float x = offset[0] + (xLen != 0 ? getNewlineStartOffset(text, 0, xLen, alignment) : 0);
+    float yTop = 0;
+    float yBot = 0;
 
-    float yTop = getGlyph('S')->bearing.y();
-    float yBot = getHeight(lineSpacing);
-    float y = offset[1] + (yBot + yTop)/2.0f;
+    if (noTopMargin) {
+        yTop = 0;
+        yBot = getHeight(1.5);
+    }
+    else {
+        yTop = getGlyph('S')->bearing.y();
+        yBot = getHeight(lineSpacing);
+    }
+
+    float y = offset[1] + (yBot + yTop) / 2.0f;
 
     // Vertices by texture.
     std::map<FontTexture*, std::vector<Renderer::Vertex>> vertMap;
@@ -670,9 +680,11 @@ TextCache* Font::buildTextCache(
         float offsetX,
         float offsetY,
         unsigned int color,
-        float lineSpacing)
+        float lineSpacing,
+        bool noTopMargin)
 {
-    return buildTextCache(text, Vector2f(offsetX, offsetY), color, 0.0f, ALIGN_LEFT, lineSpacing);
+    return buildTextCache(text, Vector2f(offsetX, offsetY), color, 0.0f, ALIGN_LEFT,
+            lineSpacing, noTopMargin);
 }
 
 void TextCache::setColor(unsigned int color)
diff --git a/es-core/src/resources/Font.h b/es-core/src/resources/Font.h
index 11648fde7..792bc020e 100644
--- a/es-core/src/resources/Font.h
+++ b/es-core/src/resources/Font.h
@@ -57,15 +57,21 @@ public:
     Vector2f sizeText(std::string text, float lineSpacing = 1.5f);
     // Returns the portion of a string that fits within the passed argument maxWidth.
     std::string getTextMaxWidth(std::string text, float maxWidth);
-    TextCache* buildTextCache(const std::string& text, float offsetX,
-            float offsetY, unsigned int color, float lineSpacing = 1.5f);
+    TextCache* buildTextCache(
+            const std::string& text,
+            float offsetX,
+            float offsetY,
+            unsigned int color,
+            float lineSpacing = 1.5f,
+            bool noTopMargin = false);
     TextCache* buildTextCache(
             const std::string& text,
             Vector2f offset,
             unsigned int color,
             float xLen,
             Alignment alignment = ALIGN_LEFT,
-            float lineSpacing = 1.5f);
+            float lineSpacing = 1.5f,
+            bool noTopMargin = false);
     void renderTextCache(TextCache* cache);
 
     // Inserts newlines into text to make it wrap properly.
diff --git a/themes/rbsimple-DE/theme.xml b/themes/rbsimple-DE/theme.xml
index e29fc6489..04fa2a784 100644
--- a/themes/rbsimple-DE/theme.xml
+++ b/themes/rbsimple-DE/theme.xml
@@ -227,7 +227,7 @@ based on: 'recalbox-multi' by the Recalbox community
         </rating>
         <text name="md_description">
             <lineSpacing>1.2</lineSpacing>
-            <pos>0.454 0.675</pos>
+            <pos>0.454 0.678</pos>
             <size>0.346 0.235</size>
             <fontSize>0.02</fontSize>
         </text>