1 /************************************************************************
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 ************************************************************************/
22 #define _WM_EXPOSE_ALL
28 #include FT_FREETYPE_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
)
39 FT_BitmapGlyph bitmap_glyph
;
45 for (ch
=0; ch
<256; ch
++) {
46 if (FT_Load_Glyph(face
,FT_Get_Char_Index(face
,ch
+(i
*256)),FT_LOAD_DEFAULT
))
49 if (FT_Get_Glyph(face
->glyph
,&glyph
))
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
;
63 if (bitmap_glyph
->top
> *bl
)
64 *bl
= bitmap_glyph
->top
;
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
)
87 FT_BitmapGlyph bitmap_glyph
;
89 fontchar_t
*character
;
109 p
= array_get_ptr(&f
->pages
,i
);
113 /* connect to freetype */
114 if (FT_Init_FreeType(&library
))
117 if (FT_New_Face(library
,f
->file
,0,&face
)) {
118 FT_Done_FreeType(library
);
122 if (FT_Select_Charmap(face
, FT_ENCODING_UNICODE
)) {
124 FT_Done_FreeType(library
);
128 /* something something characters something something */
129 if (FT_Set_Char_Size(face
,h
,h
,96,96)) {
131 FT_Done_FreeType(library
);
135 s
= font_ttf_get_page_size(face
,&mw
,&mh
,&bl
,i
);
139 FT_Done_FreeType(library
);
143 p
= malloc(sizeof(fontpage_t
));
146 FT_Done_FreeType(library
);
152 p
->pixels
= malloc(gw
);
156 FT_Done_FreeType(library
);
160 array_init(&p
->sizes
,ARRAY_TYPE_PTR
);
162 memset(p
->pixels
,0,gw
);
167 for (ch
=0; ch
<256; ch
++) {
168 if (FT_Load_Glyph(face
,FT_Get_Char_Index(face
,ch
+(i
*256)),FT_LOAD_DEFAULT
))
171 if (FT_Get_Glyph(face
->glyph
,&glyph
))
174 /* make a bitmap of the glyph */
175 FT_Glyph_To_Bitmap(&glyph
,ft_render_mode_normal
,0,1);
176 bitmap_glyph
= (FT_BitmapGlyph
)glyph
;
178 /* TODO: a less shitty way to do this, should calculate for rows/columns */
179 gw
= bitmap_glyph
->bitmap
.width
;
180 gh
= bitmap_glyph
->bitmap
.rows
;
181 character
= malloc(sizeof(fontchar_t
));
182 character
->x
[0] = (float)((float)sx
/(float)s
);
183 character
->y
[0] = (float)((float)sy
/(float)s
);
184 character
->x
[1] = (float)character
->x
[0]+(float)((float)mw
/(float)s
);
185 character
->y
[1] = (float)character
->y
[0]+(float)((float)mh
/(float)s
);
186 character
->a
= (face
->glyph
->advance
.x
>> 6);
190 array_push_ptr(&p
->sizes
,character
);
191 for (j
=0; j
<mh
; j
++) {
192 for (k
=0; k
<mw
; k
++) {
194 ay
= 2*((sy
+j
)+(bl
-bitmap_glyph
->top
));
198 if (k
>= bitmap_glyph
->bitmap
.width
|| j
>= bitmap_glyph
->bitmap
.rows
) {
201 p
->pixels
[l
] = bitmap_glyph
->bitmap
.buffer
[k
+ bitmap_glyph
->bitmap
.width
*j
];
211 FT_Done_Glyph(glyph
);
214 glGenTextures(1,&p
->glid
);
215 glBindTexture(GL_TEXTURE_2D
, p
->glid
);
217 b
= opengl_has_bilinear();
218 t
= opengl_has_trilinear();
219 m
= opengl_has_mipmap();
221 /* draw the pixels to the texture */
222 glTexImage2D(GL_TEXTURE_2D
,0,GL_RGBA8
,s
,s
,0,GL_LUMINANCE_ALPHA
,GL_UNSIGNED_BYTE
,p
->pixels
);
225 /* shouldn't ever need this, but there's an ATI/AMD bug that this fixes */
226 glEnable(GL_TEXTURE_2D
);
227 glGenerateMipmap(GL_TEXTURE_2D
);
228 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
229 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
233 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
235 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
237 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
240 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
241 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
243 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
244 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
247 if (opengl_has_anisotropic()) {
248 float ma
= opengl_max_anisotropic();
249 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, ma
);
254 FT_Done_FreeType(library
);
256 array_set_ptr(&f
->pages
,p
,i
);
261 /* load a true type font file */
262 int font_load_ttf(font_t
*f
, char* file
)
264 f
->file
= path_get("font",file
,1,NULL
,0);
269 array_init(&f
->pages
,ARRAY_TYPE_PTR
);
271 /* create the ascii fontpage */
272 if (font_ttf_gen_fontpage(f
,0))
273 vlprintf(CN_WARN
, "font_load_ttf: failed to generate ASCII fontpage");
278 /* returns the opengl texture id and texcoords for a character */
279 int font_ttf_get_char(font_t
*f
, uint32_t ch
, fontchar_t
**fc
, GLuint
*glid
)
285 if (font_ttf_gen_fontpage(f
,pid
))
288 p
= array_get_ptr(&f
->pages
,pid
);
292 *fc
= array_get_ptr(&p
->sizes
,ch
%256);