summaryrefslogtreecommitdiff
path: root/libcore/fontmanager.c
blob: 1bca226bc65005595361ab0b7668cac9c9df5fa3 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include "fontmanager.h"
#include "../config.h"
#include <ft2build.h>   
#include FT_FREETYPE_H

using namespace std;

cMutex cFontManager::mutex;

cFontManager::cFontManager() {
}

cFontManager::~cFontManager() {
    DeleteFonts();
}

void cFontManager::CacheFonts(cTemplate *tpl) {
    cMutexLock MutexLock(&mutex);

    vector< pair<string, int> > usedFonts = tpl->GetUsedFonts();

    cStringList availableFonts;
    cFont::GetAvailableFontNames(&availableFonts);

    for (vector< pair<string, int> >::iterator ft = usedFonts.begin(); ft != usedFonts.end(); ft++) {
        string fontName = ft->first;
        int fontSize = ft->second;
        if (fontSize < 1) {
            continue;
        }

        int fontAvailable = availableFonts.Find(fontName.c_str());
        if (fontAvailable == -1) {
            esyslog("skindesigner: font %s not available, skipping", fontName.c_str());
            continue;
        }

        InsertFont(fontName, fontSize);
    }
}

void cFontManager::Debug(void) {
    dsyslog("skindesigner: fontmanager fonts available:");
    for (map < string, map< int, cFont* > >::iterator fts = fonts.begin(); fts != fonts.end(); fts++) {
        dsyslog("skindesigner: FontName %s", fts->first.c_str());
        for (map<int, cFont*>::iterator ftSizes = (fts->second).begin(); ftSizes != (fts->second).end(); ftSizes++) {
            int confHeight = ftSizes->first;
            int realHeight = (ftSizes->second)->Height();
            dsyslog("skindesigner: fontSize %d, fontHeight %d, ratio %f", confHeight, realHeight, (double)confHeight / (double)realHeight);
        }
    }
}

void cFontManager::ListAvailableFonts(void) {
    cStringList availableFonts;
    cFont::GetAvailableFontNames(&availableFonts);
    int numFonts = availableFonts.Size();
    esyslog("skindesigner: %d Fonts available:", numFonts);
    for (int i=0; i<numFonts; i++) {
        esyslog("skindesigner: font %d: %s", i, availableFonts[i]);
    }
}

void cFontManager::DeleteFonts() {
    cMutexLock MutexLock(&mutex);
    for(map<string, map<int,cFont*> >::iterator it = fonts.begin(); it != fonts.end(); it++) {
        for(map<int,cFont*>::iterator it2 = (it->second).begin(); it2 != (it->second).end(); it2++) {
            delete it2->second;
        }
    }
    fonts.clear();
}

int cFontManager::Width(string fontName, int fontSize, const char *text) {
    cMutexLock MutexLock(&mutex);
    if (!text)
        return 0;
    cFont *font = GetFont(fontName, fontSize);
    //if not already cached, load it new
    if (!font)
        InsertFont(fontName, fontSize);
    font = GetFont(fontName, fontSize);
    if (!font)
        return 0;
    int width = font->Width(text);
    return width;
}

int cFontManager::Height(string fontName, int fontSize) {
    cMutexLock MutexLock(&mutex);
    cFont *font = GetFont(fontName, fontSize);
    //if not already cached, load it new
    if (!font)
        InsertFont(fontName, fontSize);
    font = GetFont(fontName, fontSize);
    if (!font)
        return 0;
    return font->Height();
}

cFont *cFontManager::Font(string fontName, int fontSize) {
    cMutexLock MutexLock(&mutex);
    cFont *font = GetFont(fontName, fontSize);
    //if not already cached, load it new
    if (!font)
        InsertFont(fontName, fontSize);
    font = GetFont(fontName, fontSize);
    return font;
}

cFont *cFontManager::FontUncached(string fontName, int fontSize) {
    cMutexLock MutexLock(&mutex);
    cFont *font = CreateFont(fontName, fontSize);
    return font;
}

/********************************************************************************
* Private Functions 
********************************************************************************/

cFont *cFontManager::CreateFont(string name, int size) {
    cMutexLock MutexLock(&mutex);
    cFont *fontTmp = cFont::CreateFont(name.c_str(), size);
    if (!fontTmp)
        fontTmp = cFont::CreateFont(Setup.FontOsd, size);
    int realHeight = fontTmp->Height();
    delete fontTmp;
    cFont *font = cFont::CreateFont(name.c_str(), (double)size / (double)realHeight * (double)size);
    if (!font)
        font = cFont::CreateFont(Setup.FontOsd, (double)size / (double)realHeight * (double)size);
    return font;
}

void cFontManager::InsertFont(string name, int size) {
    cFont *newFont = CreateFont(name, size);
    if (!newFont)
        return;
    map < string, map< int, cFont* > >::iterator hit = fonts.find(name);
    if (hit != fonts.end()) {
        (hit->second).insert(pair<int, cFont*>(size, newFont));
    } else {
        map<int, cFont*> fontsizes;
        fontsizes.insert(pair<int, cFont*>(size, newFont));
        fonts.insert(pair<string, map<int, cFont*> >(name, fontsizes));
    }
}

cFont *cFontManager::GetFont(string name, int size) {
    map< string, map<int,cFont*> >::iterator hitName = fonts.find(name);
    if (hitName == fonts.end())
        return NULL;
    map<int,cFont*>::iterator hitSize = (hitName->second).find(size);
    if (hitSize == (hitName->second).end())
        return NULL;
    return hitSize->second;
}

int cFontManager::GetFontHeight(const char *name, int height, int charWidth) {
    FT_Library library;
    FT_Face face;
    cString fontFileName = cFont::GetFontFileName(name);
    
    int descender = 0;
    int y_ppem = 0;
    int error = FT_Init_FreeType(&library);
    if (error) return 0;
    error = FT_New_Face(library, fontFileName, 0, &face);
    if (error) return 0;
    error = FT_Set_Char_Size(face, charWidth * 64, height * 64, 0, 0);
    if (error) return 0;

    descender = face->size->metrics.descender/64;
    y_ppem = face->size->metrics.y_ppem;
    int realHeight = y_ppem + descender;

    FT_Done_Face(face);
    FT_Done_FreeType(library);

    return realHeight;
}

bool cFontManager::FontInstalled(string fontName) {
    cStringList availableFonts;
    cFont::GetAvailableFontNames(&availableFonts);
    int numFonts = availableFonts.Size();
    string compare = fontName + ":";
    for (int i=0; i<numFonts; i++) {
        string currentFont = availableFonts[i];
        if (currentFont.find(compare) == 0) {
            return true;
        }
    }
    return false;
}