aboutsummaryrefslogtreecommitdiff
path: root/include/Text.hpp
blob: bc6f7ab314681a37cf5b94a797f180e805adbd35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#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), is_japanese(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
        bool is_japanese;
    };
    
    class Text
    {
    public:
        Text(const sf::Font *font, const sf::Font *cjk_font);
        Text(sf::String str, const sf::Font *font, const sf::Font *cjk_font, unsigned int characterSize, float maxWidth, bool plainText = true);
        
        void setString(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);

        // Note: won't update until @draw is called
        float getWidth() const;
        
        // Note: 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
        };
        
#if 0
        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;
#endif

        void splitTextByFont();
    private:
        sf::String str;
        const sf::Font *font;
        const sf::Font *cjk_font;
        unsigned int characterSize;
        sf::VertexArray vertices[2];
        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;
    };
}