1 /*
2 * Komposter
3 *
4 * Copyright (c) 2010 Noora Halme et al. (see AUTHORS)
5 *
6 * This code is licensed under the GNU General Public
7 * License version 2. See LICENSE for full text.
8 *
9 * Font loading, pre-rendering and drawing to display
10 *
11 */
12
13 #include "font.h"
14
15 // number of font styles specified
16 #define FONT_STYLES 8
17
18 // from main.c
19 extern char respath[512];
20
21 // eight font styles
22 char fontfile[FONT_STYLES][255]={
23 "m42.TTF", // komposter title font
24 "",
25 "acknowtt.ttf", // tiny pixel font for modules
26 "078MKSD_MC.TTF", // module descriptions
27 "m42.TTF", // title font at 8x scale
28 "",
29 "",
30 "",
31 };
32 int fontsize[FONT_STYLES]={
33 8,
34 0,
35 13, //12,
36 22, //16,
37 64,
38 0,
39 0,
40 0
41 };
42
43
44 // freetype library struct and font face structs
45 FT_Library ft;
46 FT_Face font[FONT_STYLES];
47
48 // data for prerendered font bitmaps
49 int font_advance[FONT_STYLES][255];
50 int font_xoffset[FONT_STYLES][255];
51 int font_yoffset[FONT_STYLES][255];
52 int font_width[FONT_STYLES][255];
53 int font_height[FONT_STYLES][255];
54 float font_ucoord[FONT_STYLES][255];
55 float font_vcoord[FONT_STYLES][255];
56 GLuint font_texture[FONT_STYLES][255];
57 u32 *font_bitmap[FONT_STYLES][255];
58
59
60 // round a 32-bit value upward to nearest power of 2
tpow2(unsigned int x)61 unsigned int tpow2(unsigned int x)
62 { x--;x|=x>>1;x|=x>>2;x|=x>>4;x|=x>>8;x|=x>>16;x++;return x; }
63
64
65 // initialize freetype, load font faces and prerender the font
66 // glyphs with sizes specified in the global font settings
font_init(void)67 int font_init(void)
68 {
69 char fullpath[512];
70 int err, i, j, c, rc, f, texw, texh;
71 GLuint p;
72 FT_GlyphSlot slot;
73
74 // init freetype
75 err=FT_Init_FreeType(&ft);
76 if (err) {
77 printf("Freetype error on FT_Init_FreeType()\n");
78 return 0;
79 }
80
81 // load font faces and set sizes
82 for(i=0;i<FONT_STYLES;i++) {
83 strncpy(fullpath, respath, 511);
84 strncat(fullpath, fontfile[i], 511);
85 if (fontsize[i] > 0) {
86 // err=FT_New_Face(ft, fontfile[i], 0, &font[i]);
87 err=FT_New_Face(ft, fullpath, 0, &font[i]);
88 if (err) {
89 printf("Freetype error on FT_New_Face(), path %s\n", fullpath);
90 return 0;
91 }
92 err=FT_Set_Pixel_Sizes(font[i], 0, fontsize[i]);
93 // err=FT_Set_Pixel_Sizes(font[i], fontsize[i], fontsize[i]);
94 }
95 }
96
97 // prerender all glyphs
98 for(f=0;f<FONT_STYLES;f++) {
99 if (fontsize[f] > 0) {
100 slot=font[f]->glyph;
101 for(c=0;c<255;c++) {
102 // awful kludge to fix W and M with the bitmap font
103 rc=c;
104 if (c=='W') rc='w';
105 if (c=='M') rc='m';
106
107 // render character
108 err=FT_Load_Char(font[f], rc, FT_LOAD_RENDER);
109 if (err) {
110 printf("Freetype error on FT_Load_Char()\n");
111 continue;
112 }
113
114 // save metrics
115 font_advance[f][c]=slot->advance.x >> 6;
116 font_xoffset[f][c]=slot->bitmap_left;
117 font_yoffset[f][c]=-slot->bitmap_top;
118 font_width[f][c]=slot->bitmap.width;
119 font_height[f][c]=slot->bitmap.rows;
120 texw=tpow2(slot->bitmap.width);
121 texh=tpow2(slot->bitmap.rows);
122 font_ucoord[f][c]=(float)(slot->bitmap.width)/(float)(texw);
123 font_vcoord[f][c]=(float)(slot->bitmap.rows)/(float)(texh);
124
125 // alloc ram for bimap and convert to RGBA
126 font_bitmap[f][c]=calloc(texw*texh, sizeof(GLuint));
127 for (j=0;j<slot->bitmap.rows;j++)
128 {
129 for(i=0;i<slot->bitmap.width;i++) {
130 p= 0xffffff|((u32)(slot->bitmap.buffer[j*slot->bitmap.pitch+i]) << 24);
131 font_bitmap[f][c][ ( slot->bitmap.rows-(j+1) )*texw + i] = p;
132 }
133 }
134
135 // generate opengl texture for the bitmap
136 glEnable(GL_TEXTURE_2D);
137 glGenTextures(1, &font_texture[f][c]);
138 glBindTexture(GL_TEXTURE_2D, font_texture[f][c]);
139 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, font_bitmap[f][c]);
140 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
141 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
142 glDisable(GL_TEXTURE_2D);
143 }
144 }
145 }
146
147 return 1;
148 }
149
150
151
152
153 // render text using a preloaded face/size
154 // fontnr is preloaded face/size number, color is argb
155 // align 0=left, 1=center, 2=right
render_text(const char * text,float x,float y,int fontnr,u32 color,int align)156 void render_text(const char *text, float x, float y, int fontnr, u32 color, int align)
157 {
158 unsigned long sw, n;
159 float xp, yp;
160
161 // calc text bitmap width (note: linefeeds fuck up center and right alignment)
162 sw=0; n=0;
163 while(n<strlen(text))
164 {
165 sw+=font_advance[fontnr][(int)text[n]];
166 n++;
167 }
168
169 // render the string using textured quads
170 xp=x;
171 if (align==1) xp-=(sw/2);
172 if (align==2) xp-=sw;
173 yp=y; n=0;
174 while(n<strlen(text))
175 {
176 if ((int)text[n]=='\n') { yp+=fontsize[fontnr]+2; xp=x; n++; continue; }
177 glEnable(GL_TEXTURE_2D);
178 glColor4ub((color>>16)&0xff, (color>>8)&0xff, color&0xff, color>>24);
179 glBindTexture(GL_TEXTURE_2D, font_texture[fontnr][(int)text[n]]);
180 glBegin(GL_QUADS);
181 glTexCoord2f(0, font_vcoord[fontnr][(int)text[n]]);
182 glVertex2f(xp+font_xoffset[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
183 glTexCoord2f(font_ucoord[fontnr][(int)text[n]], font_vcoord[fontnr][(int)text[n]]);
184 glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
185 glTexCoord2f(font_ucoord[fontnr][(int)text[n]], 0);
186 glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]],
187 yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
188 glTexCoord2f(0, 0);
189 glVertex2f(xp+font_xoffset[fontnr][(int)text[n]],
190 yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
191 glEnd();
192 glDisable(GL_TEXTURE_2D);
193
194 xp+=font_advance[fontnr][(int)text[n]];
195 n++;
196 }
197 }
198
199