From 795cc3d873df13bfe2abaa56b17ea247bc892c20 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 20 Jul 2020 15:06:37 +0200 Subject: Word-wrap body text --- include/Text.hpp | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 include/Text.hpp (limited to 'include/Text.hpp') 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 +#include +#include +#include +#include +#include +#include +#include "types.hpp" +#include + +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 textElements; + + int caretIndex; + sf::Vector2f caretPosition; + sf::Clock lastSeenTimer; + sf::Vector2u renderTargetSize; + }; +} -- cgit v1.2.3