aboutsummaryrefslogtreecommitdiff
path: root/include/Text.hpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-07-20 15:06:37 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-20 15:06:37 +0200
commit795cc3d873df13bfe2abaa56b17ea247bc892c20 (patch)
tree45f5918e7778fe5793f8636747f2834ba01ef141 /include/Text.hpp
parentf52d48906f7fad95353da3cc7ddfe75b12106e4e (diff)
Word-wrap body text
Diffstat (limited to 'include/Text.hpp')
-rw-r--r--include/Text.hpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/include/Text.hpp b/include/Text.hpp
new file mode 100644
index 0000000..8b6c0b9
--- /dev/null
+++ b/include/Text.hpp
@@ -0,0 +1,126 @@
+#pragma once
+
+#include <SFML/Graphics/VertexArray.hpp>
+#include <SFML/Graphics/Font.hpp>
+#include <SFML/Graphics/RenderTarget.hpp>
+#include <SFML/Window/Event.hpp>
+#include <SFML/System/String.hpp>
+#include <SFML/System/Clock.hpp>
+#include <vector>
+#include "types.hpp"
+#include <assert.h>
+
+namespace QuickMedia
+{
+ struct StringViewUtf32 {
+ const u32 *data;
+ size_t size;
+
+ StringViewUtf32() : data(nullptr), size(0) {}
+ StringViewUtf32(const u32 *data, usize size) : data(data), size(size) {}
+
+ size_t find(const StringViewUtf32 &other, size_t offset = 0) const;
+
+ u32 operator [] (usize index) const {
+ assert(index < size);
+ return data[index];
+ }
+ };
+
+ struct TextElement
+ {
+ enum class Type
+ {
+ TEXT
+ };
+
+ TextElement() {}
+ TextElement(const StringViewUtf32 &_text, Type _type) : text(_text), type(_type), ownLine(false) {}
+
+ StringViewUtf32 text;
+ sf::Vector2f position;
+ Type type;
+ bool ownLine; // Currently only used for emoji, to make emoji bigger when it's the only thing on a line
+ };
+
+ class Text
+ {
+ public:
+ Text(const sf::Font *font);
+ Text(const sf::String &str, const sf::Font *font, unsigned int characterSize, float maxWidth, bool plainText = true);
+
+ void setString(const sf::String &str);
+ const sf::String& getString() const;
+
+ void setPosition(float x, float y);
+ void setPosition(const sf::Vector2f &position);
+ sf::Vector2f getPosition() const;
+
+ void setMaxWidth(float maxWidth);
+ float getMaxWidth() const;
+
+ void setCharacterSize(unsigned int characterSize);
+ unsigned int getCharacterSize() const;
+
+ const sf::Font* getFont() const;
+
+ void setFillColor(sf::Color color);
+ void setLineSpacing(float lineSpacing);
+ void setCharacterSpacing(float characterSpacing);
+ void setEditable(bool editable);
+
+ // Warning: won't update until @draw is called
+ float getHeight() const;
+
+ void processEvent(const sf::Event &event);
+
+ // Performs culling. @updateGeometry is called even if text is not visible if text is dirty, because updateGeometry might change the dimension of the text and make is visible.
+ // Returns true if text was drawn on screen (if text is within window borders)
+ bool draw(sf::RenderTarget &target);
+
+ void updateGeometry(bool update_even_if_not_dirty = false);
+ private:
+ enum class CaretMoveDirection : u8
+ {
+ NONE,
+ UP,
+ DOWN,
+ HOME,
+ END
+ };
+
+ void updateCaret();
+ bool isCaretAtEnd() const;
+ int getStartOfLine(int startIndex) const;
+ int getEndOfLine(int startIndex) const;
+ int getRowByPosition(const sf::Vector2f &position) const;
+
+ int getPreviousLineClosestPosition(int startIndex) const;
+ int getNextLineClosestPosition(int startIndex) const;
+ private:
+ sf::String str;
+ const sf::Font *font;
+ unsigned int characterSize;
+ sf::VertexArray vertices;
+ float maxWidth;
+ sf::Vector2f position;
+ sf::Color color;
+ sf::Color urlColor;
+ bool dirty;
+ bool dirtyText;
+ bool dirtyCaret;
+ bool plainText;
+ bool editable;
+ bool visible;
+ CaretMoveDirection caretMoveDirection;
+ sf::FloatRect boundingBox;
+ float lineSpacing;
+ float characterSpacing;
+ std::vector<TextElement> textElements;
+
+ int caretIndex;
+ sf::Vector2f caretPosition;
+ sf::Clock lastSeenTimer;
+ sf::Vector2u renderTargetSize;
+ };
+}