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
)
84 GLint swizzleMask
[4] = {GL_RED
, GL_RED
, GL_RED
, GL_GREEN
};
88 FT_BitmapGlyph bitmap_glyph
;
90 fontchar_t
*character
;
110 p
= array_get_ptr(&f
->pages
,i
);
114 /* connect to freetype */
115 if (FT_Init_FreeType(&library
))
118 if (FT_New_Face(library
,f
->file
,0,&face
)) {
119 FT_Done_FreeType(library
);
123 if (FT_Select_Charmap(face
, FT_ENCODING_UNICODE
)) {
125 FT_Done_FreeType(library
);
129 /* something something characters something something */
130 if (FT_Set_Char_Size(face
,h
,h
,96,96)) {
132 FT_Done_FreeType(library
);
136 s
= font_ttf_get_page_size(face
,&mw
,&mh
,&bl
,i
);
140 FT_Done_FreeType(library
);
144 p
= malloc(sizeof(fontpage_t
));
147 FT_Done_FreeType(library
);
153 p
->pixels
= malloc(gw
);
157 FT_Done_FreeType(library
);
161 array_init(&p
->sizes
,ARRAY_TYPE_PTR
);
163 memset(p
->pixels
,0,gw
);
168 for (ch
=0; ch
<256; ch
++) {
169 if (FT_Load_Glyph(face
,FT_Get_Char_Index(face
,ch
+(i
*256)),FT_LOAD_DEFAULT
))
172 if (FT_Get_Glyph(face
->glyph
,&glyph
))
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);
191 array_push_ptr(&p
->sizes
,character
);
192 for (j
=0; j
<mh
; j
++) {
193 for (k
=0; k
<mw
; k
++) {
195 ay
= 2*((sy
+j
)+(bl
-bitmap_glyph
->top
));
199 if (k
>= bitmap_glyph
->bitmap
.width
|| j
>= bitmap_glyph
->bitmap
.rows
) {
202 p
->pixels
[l
] = bitmap_glyph
->bitmap
.buffer
[k
+ bitmap_glyph
->bitmap
.width
*j
];
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
);
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
);
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 if (opengl_has_anisotropic()) {
241 float ma
= opengl_max_anisotropic();
242 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, ma
);
247 FT_Done_FreeType(library
);
249 array_set_ptr(&f
->pages
,p
,i
);
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);
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");
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
)
278 if (font_ttf_gen_fontpage(f
,pid
))
281 p
= array_get_ptr(&f
->pages
,pid
);
285 *fc
= array_get_ptr(&p
->sizes
,ch
%256);