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
|
#include <stdexcept>
#include "fscalc.h"
Font::Font(std::string s, int slant, int weight) {
FcPattern *tmp1, *tmp2, *final;
FcResult res;
FcChar8 *filename;
int fontindex;
if(!(fc = FcInitLoadConfigAndFonts()))
throw(std::runtime_error("failed to initialize fontconfig"));
if(FT_Init_FreeType(&library))
throw(std::runtime_error("failed to initialize freetype"));
aux = FcPatternCreate();
tmp1 = FcPatternBuild(NULL,
FC_FAMILY, FcTypeString, s.c_str(),
FC_SLANT, FcTypeInteger, slant,
FC_WEIGHT, FcTypeInteger, weight ? 300 : 100,
NULL);
if(!tmp1)
throw(std::runtime_error("failed to load font"));
tmp2 = FcFontRenderPrepare(fc, tmp1, aux);
FcPatternDestroy(tmp1);
final = FcFontMatch(fc, tmp2, &res);
FcPatternDestroy(tmp2);
if(!final)
throw(std::runtime_error("failed to load font"));
if(FcPatternGetString(final, FC_FILE, 0, &filename) != FcResultMatch || FcPatternGetInteger(final, FC_INDEX, 0, &fontindex) != FcResultMatch) {
FcPatternDestroy(final);
throw(std::runtime_error("failed to locate font"));
}
if(FT_New_Face(library, (char*)filename, fontindex, &face)) {
FcPatternDestroy(final);
throw(std::runtime_error("failed to create new face"));
}
FcPatternDestroy(final);
FcPatternDestroy(aux);
// FcFini();
}
Font::~Font() {
FT_Done_Face(face);
FT_Done_FreeType(library);
}
void Font::set_font_size(int size) {
FT_Size_RequestRec req;
TT_OS2 *os2;
TT_HoriHeader *hori;
float scale = 1.0;
FT_Size_Metrics *m = &face->size->metrics;
os2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
hori = (TT_HoriHeader*)FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
if(os2 && hori) {
int horisum = hori->Ascender - hori->Descender;
unsigned int winsum = os2->usWinAscent + os2->usWinDescent;
scale = (float)horisum / (float)winsum;
}
req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (FT_F26Dot6)(size * 64 * scale);
req.horiResolution = 0;
req.vertResolution = 0;
FT_Request_Size(face, &req);
}
double Font::get_kerning(FT_UInt left, FT_UInt right) {
if(FT_HAS_KERNING(face)) {
FT_Vector d;
FT_Get_Kerning(face, left, right, 0, &d);
return (double)d.x / 64.0;
} else return 0;
}
unsigned int Font::get_text_width(std::string s) {
FT_UInt prev = 0;
bool kerning = FT_HAS_KERNING(face);
double width = 0;
for(std::string::iterator c = s.begin(); c < s.end(); c++) {
FT_UInt character;
unsigned char first;
first = character = *c;
if(first & 0x80) {
character += *(++c) << 8;
if((first & 0xf0) == 0xe0) {
character += *(++c) << 16;
if((first & 0xf8) == 0xf0)
character += *(++c) << 24;
}
}
int i = FT_Get_Char_Index(face, character);
if(kerning && prev && i)
width += get_kerning(prev, i);
if(FT_Load_Char(face, *c, 0))
throw(std::runtime_error("failed to load char"));
width += (double)face->glyph->advance.x / 64.0;
}
return int(width);
}
unsigned int Font::get_line_height() {
return (face->size->metrics.ascender - face->size->metrics.descender) / 64;
}
|