summaryrefslogtreecommitdiff
path: root/src/graphics/font.cpp
blob: 42176b24e183d20e47f209d76cfa0903b4b2071f (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
#include "font.h"

using namespace Graphics;

// Font

Font::Font(const sf::Texture &texture, const std::string &mapping,
        unsigned int numrows, unsigned int numcols)
    : tex_(texture)
    , mapping_(mapping)
    , numrows_(numrows)
    , numcols_(numcols)
{
    sf::Vector2u totalSize = tex_.getSize();
    sf::Vector2f totalSize_f (totalSize.x, totalSize.y);
    glyphSize_ = sf::Vector2f( totalSize.x / numcols_, totalSize.y / numrows_ );
}

std::array<sf::Vector2f, 4> Font::getGlyphMapping(const char ch){
    unsigned int pos = static_cast<unsigned int>( mapping_.find_first_of(ch));
    if (pos == std::string::npos){
        // TODO: Error handling!
        pos = 0;
    }
    unsigned int x = pos % numcols_;
    unsigned int y = (pos - x) / numcols_;

    sf::Vector2f basePos(x*glyphSize_.x, y*glyphSize_.y);

    // 1 --- 2
    // |     |
    // 4 --- 3
    return std::array<sf::Vector2f,4> {
        basePos,
        basePos + sf::Vector2f( glyphSize_.x, 0 ),
        basePos + glyphSize_,
        basePos + sf::Vector2f( 0, glyphSize_.y ),
    };
}

sf::Vector2f Font::getGlyphSize(){
    return glyphSize_;
}

const sf::Texture * Font::getTexture(){
    return &tex_;
}




// Text

Text::Text(Font &font, const std::string &text)
    : font_(font)
    , text_(text)
    , vertices_(sf::Quads, text.size()*4)
{
    unsigned int length = vertices_.getVertexCount();
    sf::Vector2f glyphSize = font_.getGlyphSize();
    // TODO: this is the simplest rendering way: everything in one line
    //       we should improve this to make it handle newlines or max witdths
    for(unsigned int i=0; i < length; i=i+4){
        vertices_[i+0].position = sf::Vector2f(glyphSize.x * i/4,       0);
        vertices_[i+1].position = sf::Vector2f(glyphSize.x * (i/4 + 1), 0);
        vertices_[i+2].position = sf::Vector2f(glyphSize.x * (i/4 + 1), glyphSize.y);
        vertices_[i+3].position = sf::Vector2f(glyphSize.x * i/4,       glyphSize.y);

        std::array<sf::Vector2f, 4> glyph = font_.getGlyphMapping(text_[i/4]);

        vertices_[i+0].texCoords = glyph[0];
        vertices_[i+1].texCoords = glyph[1];
        vertices_[i+2].texCoords = glyph[2];
        vertices_[i+3].texCoords = glyph[3];
    }
}

void Text::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    // TODO: only repaint if needed: when repainting is needed
    // vertices_.clear() and fun
    states.transform *= getTransform();
    states.texture = font_.getTexture();
    // you may also override states.shader or states.blendMode if you want
    target.draw(vertices_, states);
}