remove deprecated luminance texture generation
[voxelands-alt.git] / src / graphics / font_ttf.c
blobe2fb490b26a4240ed56454ac08131df8158aefe0
1 /************************************************************************
2 * font.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "path.h"
22 #define _WM_EXPOSE_ALL
23 #include "wm.h"
24 #include "graphics.h"
26 #include <string.h>
27 #include <ft2build.h>
28 #include FT_FREETYPE_H
29 #include FT_GLYPH_H
30 #include FT_OUTLINE_H
31 #include FT_TRIGONOMETRY_H
33 static uint32_t font_ttf_get_page_size(FT_Face face, uint32_t *mw, uint32_t *mh, int32_t *bl, uint32_t i)
35 uint32_t w = 0;
36 uint32_t h = 0;
37 uint32_t ch;
38 FT_Glyph glyph;
39 FT_BitmapGlyph bitmap_glyph;
41 *mh = 0;
42 *mw = 0;
43 *bl = 0;
45 for (ch=0; ch<256; ch++) {
46 if (FT_Load_Glyph(face,FT_Get_Char_Index(face,ch+(i*256)),FT_LOAD_DEFAULT))
47 return 1;
49 if (FT_Get_Glyph(face->glyph,&glyph))
50 return 1;
52 /* make a bitmap of the glyph */
53 FT_Glyph_To_Bitmap(&glyph,ft_render_mode_normal,0,1);
54 bitmap_glyph = (FT_BitmapGlyph)glyph;
56 w = bitmap_glyph->bitmap.width;
57 h = bitmap_glyph->bitmap.rows;
59 if (h > *mh)
60 *mh = h;
61 if (w > *mw)
62 *mw = w;
63 if (bitmap_glyph->top > *bl)
64 *bl = bitmap_glyph->top;
67 if (!(*mw) || !(*mh))
68 return 0;
70 *mw += 6;
71 *mh += 6;
73 w = (*mw)*16;
74 h = (*mh)*16;
76 if (w > h)
77 return math_next_pow2(w);
79 return math_next_pow2(h);
82 static int font_ttf_gen_fontpage(font_t *f, uint32_t i)
84 GLint swizzleMask[4] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
85 FT_Face face;
86 FT_Library library;
87 FT_Glyph glyph;
88 FT_BitmapGlyph bitmap_glyph;
89 fontpage_t *p;
90 fontchar_t *character;
91 uint32_t s;
92 uint32_t h = 32<<6;
93 uint32_t ch;
94 uint32_t gw;
95 uint32_t gh;
96 int32_t bl;
97 uint32_t mh = 0;
98 uint32_t mw = 0;
99 uint32_t sx;
100 uint32_t sy;
101 uint32_t ax;
102 uint32_t ay;
103 int b = 0;
104 int t = 0;
105 int m = 0;
106 int j;
107 int k;
108 int l;
110 p = array_get_ptr(&f->pages,i);
111 if (p)
112 return 0;
114 /* connect to freetype */
115 if (FT_Init_FreeType(&library))
116 return 1;
118 if (FT_New_Face(library,f->file,0,&face)) {
119 FT_Done_FreeType(library);
120 return 1;
123 if (FT_Select_Charmap(face, FT_ENCODING_UNICODE)) {
124 FT_Done_Face(face);
125 FT_Done_FreeType(library);
126 return 1;
129 /* something something characters something something */
130 if (FT_Set_Char_Size(face,h,h,96,96)) {
131 FT_Done_Face(face);
132 FT_Done_FreeType(library);
133 return 1;
136 s = font_ttf_get_page_size(face,&mw,&mh,&bl,i);
138 if (!s) {
139 FT_Done_Face(face);
140 FT_Done_FreeType(library);
141 return 1;
144 p = malloc(sizeof(fontpage_t));
145 if (!p) {
146 FT_Done_Face(face);
147 FT_Done_FreeType(library);
148 return 1;
151 gw = 2*s*s;
153 p->pixels = malloc(gw);
154 if (!p->pixels) {
155 free(p);
156 FT_Done_Face(face);
157 FT_Done_FreeType(library);
158 return 1;
161 array_init(&p->sizes,ARRAY_TYPE_PTR);
163 memset(p->pixels,0,gw);
165 sx = 0;
166 sy = 0;
168 for (ch=0; ch<256; ch++) {
169 if (FT_Load_Glyph(face,FT_Get_Char_Index(face,ch+(i*256)),FT_LOAD_DEFAULT))
170 return 1;
172 if (FT_Get_Glyph(face->glyph,&glyph))
173 return 1;
175 /* make a bitmap of the glyph */
176 FT_Glyph_To_Bitmap(&glyph,ft_render_mode_normal,0,1);
177 bitmap_glyph = (FT_BitmapGlyph)glyph;
179 /* TODO: a less shitty way to do this, should calculate for rows/columns */
180 gw = bitmap_glyph->bitmap.width;
181 gh = bitmap_glyph->bitmap.rows;
182 character = malloc(sizeof(fontchar_t));
183 character->x[0] = (float)((float)sx/(float)s);
184 character->y[0] = (float)((float)sy/(float)s);
185 character->x[1] = (float)character->x[0]+(float)((float)mw/(float)s);
186 character->y[1] = (float)character->y[0]+(float)((float)mh/(float)s);
187 character->a = (face->glyph->advance.x >> 6);
188 character->w = mw;
189 character->h = mh;
191 array_push_ptr(&p->sizes,character);
192 for (j=0; j<mh; j++) {
193 for (k=0; k<mw; k++) {
194 ax = 2*((sx+k));
195 ay = 2*((sy+j)+(bl-bitmap_glyph->top));
196 l = (ax+(ay*s));
197 p->pixels[l] = 255;
198 l++;
199 if (k >= bitmap_glyph->bitmap.width || j >= bitmap_glyph->bitmap.rows) {
200 p->pixels[l] = 0;
201 }else{
202 p->pixels[l] = bitmap_glyph->bitmap.buffer[k + bitmap_glyph->bitmap.width*j];
207 sx += mw;
208 if (sx+mw > s) {
209 sx = 0;
210 sy += mh;
212 FT_Done_Glyph(glyph);
215 glGenTextures(1,&p->glid);
216 glBindTexture(GL_TEXTURE_2D, p->glid);
218 b = opengl_has_bilinear();
219 t = opengl_has_trilinear();
220 m = opengl_has_mipmap();
222 /* draw the pixels to the texture */
223 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,s,s,0,GL_RG,GL_UNSIGNED_BYTE,p->pixels);
225 if (m) {
226 glGenerateMipmap(GL_TEXTURE_2D);
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
231 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
232 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
234 if (m) {
235 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
236 }else{
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
240 if (opengl_has_anisotropic()) {
241 float ma = opengl_max_anisotropic();
242 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ma);
245 /* done! */
246 FT_Done_Face(face);
247 FT_Done_FreeType(library);
249 array_set_ptr(&f->pages,p,i);
251 return 0;
254 /* load a true type font file */
255 int font_load_ttf(font_t *f, char* file)
257 f->file = path_get("font",file,1,NULL,0);
259 if (!f->file)
260 return 1;
262 array_init(&f->pages,ARRAY_TYPE_PTR);
264 /* create the ascii fontpage */
265 if (font_ttf_gen_fontpage(f,0))
266 vlprintf(CN_WARN, "font_load_ttf: failed to generate ASCII fontpage");
268 return 0;
271 /* returns the opengl texture id and texcoords for a character */
272 int font_ttf_get_char(font_t *f, uint32_t ch, fontchar_t **fc, GLuint *glid)
274 uint32_t pid;
275 fontpage_t *p;
276 pid = ch/256;
278 if (font_ttf_gen_fontpage(f,pid))
279 return 1;
281 p = array_get_ptr(&f->pages,pid);
282 if (!p)
283 return 1;
285 *fc = array_get_ptr(&p->sizes,ch%256);
286 if (!(*fc))
287 return 1;
289 *glid = p->glid;
291 return 0;