Date:2013-07-05 20:07:46 (10 years 8 months ago)
Author:Paul Cercueil
Commit:46386a2054dfd7d302af65cc6434cf3410fc8fad
Message:Drop the bitmap font; use a TTF font instead

This allows to display UTF-8 characters, and is as such a good
step towards full internationalization.
Files: configure.in (1 diff)
src/asfont.cpp (2 diffs)
src/asfont.h (2 diffs)
src/gmenu2x.cpp (1 diff)
src/link.cpp (1 diff)

Change Details

configure.in
2121
2222AC_CHECK_LIB(SDL_gfx, rotozoomSurfaceXY,,check_sdl_gfx="no")
2323
24AC_CHECK_LIB(SDL_ttf, TTF_OpenFont)
25
2426# Check for libpng
2527AC_CHECK_LIB(png, png_read_image,,check_png="no")
2628
src/asfont.cpp
11#include "asfont.h"
2#include "imageio.h"
2#include "debug.h"
33#include "surface.h"
44#include "utilities.h"
55
6#include <algorithm>
7#include <cassert>
8#include <cstring>
6#include <SDL.h>
7#include <SDL_ttf.h>
8#include <vector>
99
10#define SFONTPLUS_CHARSET "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¿ÀÁÈÉÌÍÒÓÙÚÝÄËÏÖÜŸÂÊÎÔÛÅÃÕÑÆÇČĎĚĽĹŇÔŘŔŠŤŮŽàáèéìíòóùúýäëïöüÿâêîôûåãõñæçčďěľĺňôřŕšťžůðßÐÞþАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяØøąćęłńśżźĄĆĘŁŃŚŻŹ"
10/* TODO: Let the theme choose the font and font size */
11#define TTF_FONT "/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf"
12#define TTF_FONT_SIZE 12
1113
12ASFont::ASFont(const std::string &fontImagePath)
13    : characters(SFONTPLUS_CHARSET)
14using namespace std;
15
16ASFont::ASFont(const string &path)
1417{
15    surface = loadPNG(fontImagePath);
16    if (!surface) {
18    if (!TTF_WasInit() && TTF_Init() < 0) {
19        ERROR("Unable to init SDL_ttf library\n");
1720        return;
1821    }
19    assert(surface->format->BytesPerPixel == 4);
20
21    SDL_LockSurface(surface);
22
23    // Determine character widths.
24    Uint32 pink = SDL_MapRGB(surface->format, 255, 0, 255);
25    Uint32 *topLine = static_cast<Uint32 *>(surface->pixels);
26    const unsigned width = surface->w;
27    unsigned x = 0;
28    unsigned c = 0;
29    while (c < characters.length()) {
30        while (x < width && topLine[x] != pink) x++;
31        unsigned startx = x;
32        x++;
33        while (x < width && topLine[x] == pink) x++;
34
35        charpos.push_back(startx);
36        charpos.push_back(x);
37        if (c > 0 && utf8Code(characters[c - 1])) {
38            // UTF8 character
39            charpos.push_back(startx);
40            charpos.push_back(x);
41            c++;
42        }
43        c++;
44    }
4522
46    // Scan height of "0" glyph.
47    std::string::size_type pos = characters.find("0") * 2;
48    SDL_Rect srcrect = {
49        static_cast<Sint16>(charpos[pos]),
50        1,
51        static_cast<Uint16>(charpos[pos + 2] - charpos[pos]),
52        static_cast<Uint16>(surface->h - 1)
53    };
54    const unsigned alphaMask = surface->format->Amask;
55    unsigned y = srcrect.h;
56    bool nonTransparentFound = false;
57    while (!nonTransparentFound && y-- > 0) {
58        Uint32 *line = reinterpret_cast<Uint32 *>(
59            reinterpret_cast<Uint8 *>(surface->pixels)
60                + (srcrect.y + y) * surface->pitch
61            );
62        for (unsigned x = 0; !nonTransparentFound && x < srcrect.w; x++) {
63            nonTransparentFound = (line[srcrect.x + x] & alphaMask) != 0;
64        }
23    font = TTF_OpenFont(TTF_FONT, TTF_FONT_SIZE);
24    if (!font) {
25        ERROR("Unable to open font\n");
26        return;
6527    }
66    lineHeight = y + 1;
6728
68    SDL_UnlockSurface(surface);
29    fontheight = TTF_FontHeight(font);
6930}
7031
71ASFont::~ASFont() {
72    if (surface) {
73        SDL_FreeSurface(surface);
74    }
32ASFont::~ASFont()
33{
34    TTF_CloseFont(font);
35    TTF_Quit();
7536}
7637
77bool ASFont::utf8Code(unsigned char c) {
78    return (c>=194 && c<=198) || c==208 || c==209;
79    //return c>=194;
38int ASFont::getTextWidth(const char *text)
39{
40    int w, h;
41    TTF_SizeUTF8(font, text, &w, &h);
42    return w;
8043}
8144
82void ASFont::writeLine(Surface *s, const std::string &text, int x, int y) {
83    if (text.empty()) return;
84
85    std::string::size_type pos;
86    SDL_Rect srcrect, dstrect;
87
88    // these values won't change in the loop
89    srcrect.y = 1;
90    dstrect.y = y;
91    srcrect.h = dstrect.h = surface->h-1;
92
93    for(unsigned i=0; i<text.length() && x<surface->w; i++) {
94        //Utf8 characters
95        if (utf8Code(text[i]) && i+1<text.length()) {
96            pos = characters.find(text.substr(i,2));
97            i++;
98        } else
99            pos = characters.find(text[i]);
100        if (pos == std::string::npos) {
101            x += charpos[2]-charpos[1];
102            continue;
103        }
104
105        pos *= 2;
106
107        srcrect.x = charpos[pos];
108        srcrect.w = charpos[pos+2] - charpos[pos];
109        dstrect.x = x - charpos[pos+1] + charpos[pos];
110
111        SDL_BlitSurface(surface, &srcrect, s->raw, &dstrect);
112
113        x += charpos[pos+2] - charpos[pos+1];
45void ASFont::write(Surface *surface, const string &text,
46            int x, int y, HAlign halign, VAlign valign)
47{
48    if (text.find("\n", 0) == string::npos) {
49        writeLine(surface, text.c_str(), x, y, halign, valign);
50        return;
11451    }
115}
11652
117int ASFont::getTextWidth(const char *text) {
118    int maxWidth = 0, width = 0;
119    while (char ch = *text++) {
120        if (ch == '\n') {
121            // New line.
122            maxWidth = std::max(width, maxWidth);
123            width = 0;
124        } else {
125            std::string::size_type pos;
126            if (utf8Code(ch) && *text) {
127                // 2-byte character.
128                pos = characters.find(std::string(&text[-1], 2));
129                text++;
130            } else {
131                // 1-byte character.
132                pos = characters.find(ch);
133            }
134            if (pos == std::string::npos) {
135                pos = 0;
136            }
137            width += charpos[pos * 2 + 2] - charpos[pos * 2 + 1];
138        }
139    }
140    return std::max(width, maxWidth);
141}
53    vector<string> v;
54    split(v, text, "\n");
14255
143int ASFont::getTextWidth(const std::string& text) {
144    return getTextWidth(text.c_str());
56    for (vector<string>::const_iterator it = v.begin(); it != v.end(); it++) {
57        writeLine(surface, it->c_str(), x, y, halign, valign);
58        y += fontheight;
59    }
14560}
14661
147void ASFont::writeLine(Surface* surface, const std::string& text, int x, int y, HAlign halign) {
62void ASFont::writeLine(Surface *surface, const char *text,
63                int x, int y, HAlign halign, VAlign valign)
64{
14865    switch (halign) {
14966    case HAlignLeft:
15067        break;
...... 
15572        x -= getTextWidth(text);
15673        break;
15774    }
158    writeLine(surface, text, x, y);
159}
16075
161void ASFont::writeLine(Surface* surface, const std::string& text, int x, int y, HAlign halign, VAlign valign) {
16276    switch (valign) {
16377    case VAlignTop:
16478        break;
16579    case VAlignMiddle:
166        y -= getHeight() / 2;
80        y -= fontheight / 2;
16781        break;
16882    case VAlignBottom:
169        y -= getHeight();
83        y -= fontheight;
17084        break;
17185    }
172    writeLine(surface, text, x, y, halign);
173}
17486
175void ASFont::writeLine(Surface* surface, const std::vector<std::string> &text, int x, int y, HAlign halign, VAlign valign) {
176    switch (valign) {
177    case VAlignTop:
178        break;
179    case VAlignMiddle:
180        y -= (getHeight() / 2) * text.size();
181        break;
182    case VAlignBottom:
183        y -= getHeight() * text.size();
184        break;
185    }
87    SDL_Color color = { 0, 0, 0, 0 };
88    SDL_Surface *s = TTF_RenderUTF8_Blended(font, text, color);
18689
187    for (std::vector<std::string>::const_iterator it = text.begin(); it != text.end(); ++it) {
188        write(surface, *it, x, y, halign);
189        y += getHeight();
190    }
191}
90    SDL_Rect rect = { (Sint16) x, (Sint16) (y - 1), 0, 0 };
91    SDL_BlitSurface(s, NULL, surface->raw, &rect);
92
93    /* Note: rect.x / rect.y are reset everytime because SDL_BlitSurface
94     * will modify them if negative */
95    rect.x = x;
96    rect.y = y + 1;
97    SDL_BlitSurface(s, NULL, surface->raw, &rect);
98
99    rect.x = x - 1;
100    rect.y = y;
101    SDL_BlitSurface(s, NULL, surface->raw, &rect);
102
103    rect.x = x + 1;
104    rect.y = y;
105    SDL_BlitSurface(s, NULL, surface->raw, &rect);
106    SDL_FreeSurface(s);
107
108    rect.x = x;
109    rect.y = y;
110    color.r = 0xff;
111    color.g = 0xff;
112    color.b = 0xff;
192113
193void ASFont::write(Surface* surface, const std::string& text, int x, int y, HAlign halign, VAlign valign) {
194    if (text.find("\n", 0) != std::string::npos) {
195        std::vector<std::string> textArr;
196        split(textArr, text, "\n");
197        writeLine(surface, textArr, x, y, halign, valign);
198    } else
199        writeLine(surface, text, x, y, halign, valign);
114    s = TTF_RenderUTF8_Blended(font, text, color);
115    SDL_BlitSurface(s, NULL, surface->raw, &rect);
116    SDL_FreeSurface(s);
200117}
src/asfont.h
66#ifndef ASFONT_H
77#define ASFONT_H
88
9#include <SDL.h>
9#include <SDL_ttf.h>
1010#include <string>
1111#include <vector>
1212
...... 
2020    ASFont(const std::string &font);
2121    ~ASFont();
2222
23    bool utf8Code(unsigned char c);
24
2523    int getTextWidth(const char *text);
26    int getTextWidth(const std::string& text);
2724
28    int getHeight() {
29        return surface->h - 1;
25    int getTextWidth(const std::string& text)
26    {
27        return getTextWidth(text.c_str());
3028    }
31    int getLineHeight() {
32        return lineHeight;
29
30    bool utf8Code(unsigned char c)
31    {
32        return (c>=194 && c<=198) || c==208 || c==209;
3333    }
3434
35    void write(Surface* surface, const std::string& text, int x, int y, HAlign halign = HAlignLeft, VAlign valign = VAlignTop);
35    int getHeight()
36    {
37        return fontheight;
38    }
39
40    void write(Surface *surface,
41                const std::string &text, int x, int y,
42                HAlign halign = HAlignLeft, VAlign valign = VAlignTop);
3643
3744private:
38    void writeLine(Surface *surface, const std::string &text, int x, int y);
39    void writeLine(Surface *surface, const std::string &text, int x, int y, HAlign halign);
40    void writeLine(Surface *surface, const std::string &text, int x, int y, HAlign halign, VAlign valign);
41    void writeLine(Surface *surface, const std::vector<std::string> &text, int x, int y, HAlign halign, VAlign valign);
42
43    SDL_Surface *surface;
44    std::vector<Uint16> charpos;
45    std::string characters;
46    int lineHeight;
45    void writeLine(Surface *surface, const char *text,
46                int x, int y, HAlign halign, VAlign valign);
47
48    TTF_Font *font;
49    unsigned int fontheight;
4750};
4851
4952#endif /* ASFONT_H */
src/gmenu2x.cpp
647647    uint linksPerPage = linkColumns*linkRows;
648648    int linkSpacingX = (resX-10 - linkColumns*skinConfInt["linkWidth"])/linkColumns;
649649    int linkSpacingY = (resY-35 - skinConfInt["topBarHeight"] - linkRows*skinConfInt["linkHeight"])/linkRows;
650    uint sectionLinkPadding = (skinConfInt["topBarHeight"] - 32 - font->getLineHeight()) / 3;
650    uint sectionLinkPadding = (skinConfInt["topBarHeight"] - 32 - font->getHeight()) / 3;
651651
652652    bool quit = false;
653653    int x,y;
src/link.cpp
137137
138138void Link::recalcCoordinates() {
139139    iconX = rect.x+(rect.w-32)/2;
140    padding = (gmenu2x->skinConfInt["linkHeight"] - 32 - gmenu2x->font->getLineHeight()) / 3;
140    padding = (gmenu2x->skinConfInt["linkHeight"] - 32 - gmenu2x->font->getHeight()) / 3;
141141}
142142
143143void Link::run() {

Archive Download the corresponding diff file



interactive