4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * 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, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2009 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
36 #include FT_FREETYPE_H
39 #include "MEM_guardedalloc.h"
41 #include "DNA_listBase.h"
42 #include "DNA_vec_types.h"
44 #include "BKE_utildefines.h"
46 #include "BLI_blenlib.h"
47 #include "BLI_linklist.h" /* linknode */
48 #include "BLI_string.h"
49 #include "BLI_arithb.h"
54 #include "blf_internal_types.h"
55 #include "blf_internal.h"
58 /* freetype2 handle. */
59 FT_Library global_ft_lib;
61 int blf_font_init(void)
63 return(FT_Init_FreeType(&global_ft_lib));
66 void blf_font_exit(void)
68 FT_Done_FreeType(global_ft_lib);
71 void blf_font_size(FontBLF *font, int size, int dpi)
76 err= FT_Set_Char_Size(font->face, 0, (size * 64), dpi, dpi);
78 /* FIXME: here we can go through the fixed size and choice a close one */
79 printf("The current font don't support the size, %d and dpi, %d\n", size, dpi);
86 gc= blf_glyph_cache_find(font, size, dpi);
88 font->glyph_cache= gc;
90 gc= blf_glyph_cache_new(font);
92 font->glyph_cache= gc;
94 font->glyph_cache= NULL;
98 void blf_font_draw(FontBLF *font, char *str)
101 GlyphBLF *g, *g_prev;
103 FT_UInt glyph_index, g_prev_index;
104 float pen_x, pen_y, old_pen_x;
107 if (!font->glyph_cache)
113 has_kerning= FT_HAS_KERNING(font->face);
118 c= blf_utf8_next((unsigned char *)str, &i);
122 glyph_index= FT_Get_Char_Index(font->face, c);
123 g= blf_glyph_search(font->glyph_cache, c);
125 g= blf_glyph_add(font, glyph_index, c);
127 /* if we don't found a glyph, skip it. */
132 * This happen if we change the mode of the
133 * font, we don't drop the glyph cache, so it's
134 * possible that some glyph don't have the
135 * bitmap or texture information.
137 if (font->mode == BLF_MODE_BITMAP && (!g->bitmap_data))
138 g= blf_glyph_add(font, glyph_index, c);
139 else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data))
140 g= blf_glyph_add(font, glyph_index, c);
142 if ((font->flags & BLF_FONT_KERNING) && has_kerning && g_prev) {
147 if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
148 pen_x += delta.x >> 6;
150 if (pen_x < old_pen_x)
156 if (font->flags & BLF_USER_KERNING) {
158 pen_x += font->kerning;
160 if (pen_x < old_pen_x)
165 /* do not return this loop if clipped, we want every character tested */
166 blf_glyph_render(font, g, pen_x, pen_y);
170 g_prev_index= glyph_index;
174 void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
177 GlyphBLF *g, *g_prev;
179 FT_UInt glyph_index, g_prev_index;
181 float pen_x, pen_y, old_pen_x;
184 if (!font->glyph_cache)
188 box->xmax= -32000.0f;
190 box->ymax= -32000.0f;
195 has_kerning= FT_HAS_KERNING(font->face);
200 c= blf_utf8_next((unsigned char *)str, &i);
204 glyph_index= FT_Get_Char_Index(font->face, c);
205 g= blf_glyph_search(font->glyph_cache, c);
207 g= blf_glyph_add(font, glyph_index, c);
209 /* if we don't found a glyph, skip it. */
214 * This happen if we change the mode of the
215 * font, we don't drop the glyph cache, so it's
216 * possible that some glyph don't have the
217 * bitmap or texture information.
219 if (font->mode == BLF_MODE_BITMAP && (!g->bitmap_data))
220 g= blf_glyph_add(font, glyph_index, c);
221 else if (font->mode == BLF_MODE_TEXTURE && (!g->tex_data))
222 g= blf_glyph_add(font, glyph_index, c);
224 if ((font->flags & BLF_FONT_KERNING) && has_kerning && g_prev) {
229 if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
230 pen_x += delta.x >> 6;
232 if (pen_x < old_pen_x)
238 if (font->flags & BLF_USER_KERNING) {
240 pen_x += font->kerning;
242 if (pen_x < old_pen_x)
247 gbox.xmin= g->box.xmin + pen_x;
248 gbox.xmax= g->box.xmax + pen_x;
249 gbox.ymin= g->box.ymin + pen_y;
250 gbox.ymax= g->box.ymax + pen_y;
252 if (gbox.xmin < box->xmin)
253 box->xmin= gbox.xmin;
254 if (gbox.ymin < box->ymin)
255 box->ymin= gbox.ymin;
257 if (gbox.xmax > box->xmax)
258 box->xmax= gbox.xmax;
259 if (gbox.ymax > box->ymax)
260 box->ymax= gbox.ymax;
264 g_prev_index= glyph_index;
267 if (box->xmin > box->xmax) {
275 float blf_font_width(FontBLF *font, char *str)
279 if (!font->glyph_cache)
282 blf_font_boundbox(font, str, &box);
283 return((box.xmax - box.xmin) * font->aspect);
286 float blf_font_height(FontBLF *font, char *str)
290 if (!font->glyph_cache)
293 blf_font_boundbox(font, str, &box);
294 return((box.ymax - box.ymin) * font->aspect);
297 void blf_font_free(FontBLF *font)
301 font->glyph_cache= NULL;
302 while (font->cache.first) {
303 gc= font->cache.first;
304 BLI_remlink(&font->cache, gc);
305 blf_glyph_cache_free(gc);
308 FT_Done_Face(font->face);
310 MEM_freeN(font->filename);
312 MEM_freeN(font->name);
316 void blf_font_fill(FontBLF *font)
318 font->mode= BLF_MODE_TEXTURE;
324 font->clip_rec.xmin= 0.0f;
325 font->clip_rec.xmax= 0.0f;
326 font->clip_rec.ymin= 0.0f;
327 font->clip_rec.ymax= 0.0f;
328 font->flags= BLF_USER_KERNING | BLF_FONT_KERNING;
332 font->cache.first= NULL;
333 font->cache.last= NULL;
334 font->glyph_cache= NULL;
336 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
339 FontBLF *blf_font_new(char *name, char *filename)
345 font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new");
346 err= FT_New_Face(global_ft_lib, filename, 0, &font->face);
352 err= FT_Select_Charmap(font->face, ft_encoding_unicode);
354 printf("Can't set the unicode character map!\n");
355 FT_Done_Face(font->face);
360 mfile= blf_dir_metrics_search(filename);
362 err= FT_Attach_File(font->face, mfile);
366 font->name= BLI_strdup(name);
367 font->filename= BLI_strdup(filename);
372 void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
376 open.flags= FT_OPEN_MEMORY;
377 open.memory_base= (FT_Byte *)mem;
378 open.memory_size= mem_size;
379 FT_Attach_Stream(font->face, &open);
382 FontBLF *blf_font_new_from_mem(char *name, unsigned char *mem, int mem_size)
387 font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new_from_mem");
388 err= FT_New_Memory_Face(global_ft_lib, mem, mem_size, 0, &font->face);
394 err= FT_Select_Charmap(font->face, ft_encoding_unicode);
396 printf("Can't set the unicode character map!\n");
397 FT_Done_Face(font->face);
402 font->name= BLI_strdup(name);
403 font->filename= NULL;