aboutsummaryrefslogtreecommitdiff
path: root/src/common/Font.cpp
blob: b5b177cf232db950d1e6879efa4635d0decc6f2b (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
#include <common/Font.hpp>

#include <fstream>
#include <iostream>


Font::~Font()
{
    Deinit();
}


bool
Font::Init(const char* path, int font_size)
{
    std::ifstream file(path, std::ios::in|std::ios::binary|std::ios::ate);
    if (!file.is_open()) {
        return false;
    }


    std::streampos end = file.tellg();
    size_t size = static_cast<size_t>(end);
    char *content = new char[size + 1];

    file.seekg(0, std::ios::beg);
    file.read(content, end);
    file.close();
    content[size] = '\0';


    // set font info
    if (!stbtt_InitFont(&m_font_info, (unsigned char*)content, 0))
    {
        std::cout << "stbtt_InitFont failed.\n";
        printf("stbtt_InitFont failed\n");
        delete[] content;
        return false;
    }


    // font settings (scale + vmetrics)
    float scale = stbtt_ScaleForPixelHeight(&m_font_info, (float)font_size);
    int baseline, ascent, descent, line_gap;
    stbtt_GetFontVMetrics(&m_font_info, &ascent, &descent, &line_gap);
    baseline = int(scale * (float)-descent);
    ascent   = int(scale * (float)ascent);
    descent  = int(scale * (float)descent);
    line_gap = int(scale * (float)line_gap);


    m_font_scale = scale;
    m_font_baseline = baseline;
    m_font_yadvance = ascent - descent + line_gap;
    m_file_content = content;


    return true;
}


void
Font::LoadGlyph(Glyph& glyph, uint32_t codepoint)
{
    int bbx0, bby0, bbx1, bby1;
    stbtt_GetCodepointBitmapBox(&m_font_info, (int)codepoint, m_font_scale, m_font_scale, &bbx0, &bby0, &bbx1, &bby1);
    int width = bbx1 - bbx0;
    int height = bby1 - bby0;


    size_t size = size_t(width * height);
    uint8_t* bitmap_flipped = new uint8_t[size];
    uint8_t* bitmap_correct = new uint8_t[size];


    stbtt_MakeCodepointBitmap(&m_font_info, bitmap_flipped, width, height, width, m_font_scale, m_font_scale, (int)codepoint);

    uint8_t* dest = bitmap_correct;
    for (int y = 0; y < height; ++y)
    {
        uint8_t* src = bitmap_flipped + size_t((height-1-y)*width);
        for (int x = 0; x < width; ++x)
        {
            *dest++ = *src++;
        }
    }
    delete[] bitmap_flipped;

    glyph.bitmap.w = width;
    glyph.bitmap.h = height;
    glyph.bitmap.pixels = std::unique_ptr<uint8_t>(bitmap_correct);


    int xadvance;
    int left_side_bearing;
    stbtt_GetCodepointHMetrics(&m_font_info, (int)codepoint, &xadvance, &left_side_bearing);
    xadvance          = (int)(m_font_scale * (float)xadvance);
    left_side_bearing = (int)(m_font_scale * (float)left_side_bearing);


    glyph.xoff = static_cast<int>(m_font_scale * (float)bbx0) + left_side_bearing;
    glyph.yoff = -bby1;
    glyph.xadvance = xadvance;

}


void
Font::Deinit()
{
    if (m_file_content) {
        delete[] m_file_content;
        m_file_content = nullptr;
    }
}