-
Notifications
You must be signed in to change notification settings - Fork 12
/
font.c
198 lines (171 loc) · 5.7 KB
/
font.c
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
196
197
/*
* Komposter
*
* Copyright (c) 2010 Noora Halme et al. (see AUTHORS)
*
* This code is licensed under the GNU General Public
* License version 2. See LICENSE for full text.
*
* Font loading, pre-rendering and drawing to display
*
*/
#include "font.h"
// number of font styles specified
#define FONT_STYLES 8
// from main.c
extern char respath[512];
// eight font styles
char fontfile[FONT_STYLES][255]={
"m42.TTF", // komposter title font
"",
"acknowtt.ttf", // tiny pixel font for modules
"078MKSD_MC.TTF", // module descriptions
"m42.TTF", // title font at 8x scale
"",
"",
"",
};
int fontsize[FONT_STYLES]={
8,
0,
13, //12,
22, //16,
64,
0,
0,
0
};
// freetype library struct and font face structs
FT_Library ft;
FT_Face font[FONT_STYLES];
// data for prerendered font bitmaps
int font_advance[FONT_STYLES][255];
int font_xoffset[FONT_STYLES][255];
int font_yoffset[FONT_STYLES][255];
int font_width[FONT_STYLES][255];
int font_height[FONT_STYLES][255];
float font_ucoord[FONT_STYLES][255];
float font_vcoord[FONT_STYLES][255];
GLuint font_texture[FONT_STYLES][255];
u32 *font_bitmap[FONT_STYLES][255];
// round a 32-bit value upward to nearest power of 2
unsigned int tpow2(unsigned int x)
{ x--;x|=x>>1;x|=x>>2;x|=x>>4;x|=x>>8;x|=x>>16;x++;return x; }
// initialize freetype, load font faces and prerender the font
// glyphs with sizes specified in the global font settings
int font_init(void)
{
char fullpath[512];
int err, i, j, c, rc, f, texw, texh;
GLuint p;
FT_GlyphSlot slot;
// init freetype
err=FT_Init_FreeType(&ft);
if (err) {
printf("Freetype error on FT_Init_FreeType()\n");
return 0;
}
// load font faces and set sizes
for(i=0;i<FONT_STYLES;i++) {
strncpy(fullpath, respath, 511);
strncat(fullpath, fontfile[i], 511);
if (fontsize[i] > 0) {
// err=FT_New_Face(ft, fontfile[i], 0, &font[i]);
err=FT_New_Face(ft, fullpath, 0, &font[i]);
if (err) {
printf("Freetype error on FT_New_Face(), path %s\n", fullpath);
return 0;
}
err=FT_Set_Pixel_Sizes(font[i], 0, fontsize[i]);
// err=FT_Set_Pixel_Sizes(font[i], fontsize[i], fontsize[i]);
}
}
// prerender all glyphs
for(f=0;f<FONT_STYLES;f++) {
if (fontsize[f] > 0) {
slot=font[f]->glyph;
for(c=0;c<255;c++) {
// awful kludge to fix W and M with the bitmap font
rc=c;
if (c=='W') rc='w';
if (c=='M') rc='m';
// render character
err=FT_Load_Char(font[f], rc, FT_LOAD_RENDER);
if (err) {
printf("Freetype error on FT_Load_Char()\n");
continue;
}
// save metrics
font_advance[f][c]=slot->advance.x >> 6;
font_xoffset[f][c]=slot->bitmap_left;
font_yoffset[f][c]=-slot->bitmap_top;
font_width[f][c]=slot->bitmap.width;
font_height[f][c]=slot->bitmap.rows;
texw=tpow2(slot->bitmap.width);
texh=tpow2(slot->bitmap.rows);
font_ucoord[f][c]=(float)(slot->bitmap.width)/(float)(texw);
font_vcoord[f][c]=(float)(slot->bitmap.rows)/(float)(texh);
// alloc ram for bimap and convert to RGBA
font_bitmap[f][c]=calloc(texw*texh, sizeof(GLuint));
for (j=0;j<slot->bitmap.rows;j++)
{
for(i=0;i<slot->bitmap.width;i++) {
p= 0xffffff|((u32)(slot->bitmap.buffer[j*slot->bitmap.pitch+i]) << 24);
font_bitmap[f][c][ ( slot->bitmap.rows-(j+1) )*texw + i] = p;
}
}
// generate opengl texture for the bitmap
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &font_texture[f][c]);
glBindTexture(GL_TEXTURE_2D, font_texture[f][c]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, font_bitmap[f][c]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glDisable(GL_TEXTURE_2D);
}
}
}
return 1;
}
// render text using a preloaded face/size
// fontnr is preloaded face/size number, color is argb
// align 0=left, 1=center, 2=right
void render_text(const char *text, float x, float y, int fontnr, u32 color, int align)
{
unsigned long sw, n;
float xp, yp;
// calc text bitmap width (note: linefeeds fuck up center and right alignment)
sw=0; n=0;
while(n<strlen(text))
{
sw+=font_advance[fontnr][(int)text[n]];
n++;
}
// render the string using textured quads
xp=x;
if (align==1) xp-=(sw/2);
if (align==2) xp-=sw;
yp=y; n=0;
while(n<strlen(text))
{
if ((int)text[n]=='\n') { yp+=fontsize[fontnr]+2; xp=x; n++; continue; }
glEnable(GL_TEXTURE_2D);
glColor4ub((color>>16)&0xff, (color>>8)&0xff, color&0xff, color>>24);
glBindTexture(GL_TEXTURE_2D, font_texture[fontnr][(int)text[n]]);
glBegin(GL_QUADS);
glTexCoord2f(0, font_vcoord[fontnr][(int)text[n]]);
glVertex2f(xp+font_xoffset[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
glTexCoord2f(font_ucoord[fontnr][(int)text[n]], font_vcoord[fontnr][(int)text[n]]);
glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
glTexCoord2f(font_ucoord[fontnr][(int)text[n]], 0);
glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]],
yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
glTexCoord2f(0, 0);
glVertex2f(xp+font_xoffset[fontnr][(int)text[n]],
yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
glEnd();
glDisable(GL_TEXTURE_2D);
xp+=font_advance[fontnr][(int)text[n]];
n++;
}
}