62a64851109f293e584d39318ab5760fb282db73
[blender-staging.git] / source / blender / blenfont / intern / blf_font.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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. 
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #ifdef WITH_FREETYPE2
34
35 #include <ft2build.h>
36
37 #include FT_FREETYPE_H
38 #include FT_GLYPH_H
39
40 #endif /* WITH_FREETYPE2 */
41
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_listBase.h"
45 #include "DNA_vec_types.h"
46
47 #include "BKE_utildefines.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_linklist.h"       /* linknode */
51 #include "BLI_string.h"
52 #include "BLI_arithb.h"
53
54 #include "BIF_gl.h"
55
56 #include "blf_internal_types.h"
57 #include "blf_internal.h"
58
59
60 #ifdef WITH_FREETYPE2
61
62 /* freetype2 handle. */
63 FT_Library global_ft_lib;
64
65 int blf_font_init(void)
66 {
67         return(FT_Init_FreeType(&global_ft_lib));
68 }
69
70 void blf_font_exit(void)
71 {
72         FT_Done_FreeType(global_ft_lib);
73 }
74
75 void blf_font_fill(FontBLF *font)
76 {
77         font->ref= 1;
78         font->aspect= 1.0f;
79         font->pos[0]= 0.0f;
80         font->pos[1]= 0.0f;
81         font->angle[0]= 0.0f;
82         font->angle[1]= 0.0f;
83         font->angle[2]= 0.0f;
84         Mat4One(font->mat);
85         font->clip_rec.xmin= 0.0f;
86         font->clip_rec.xmax= 0.0f;
87         font->clip_rec.ymin= 0.0f;
88         font->clip_rec.ymax= 0.0f;
89         font->clip_mode= BLF_CLIP_DISABLE;
90         font->dpi= 0;
91         font->size= 0;
92         font->cache.first= NULL;
93         font->cache.last= NULL;
94         font->glyph_cache= NULL;
95         glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
96 }
97
98 FontBLF *blf_font_new(char *name, char *filename)
99 {
100         FontBLF *font;
101         FT_Error err;
102
103         font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new");
104         err= FT_New_Face(global_ft_lib, filename, 0, &font->face);
105         if (err) {
106                 MEM_freeN(font);
107                 return(NULL);
108         }
109
110         err= FT_Select_Charmap(font->face, ft_encoding_unicode);
111         if (err) {
112                 printf("Can't set the unicode character map!\n");
113                 FT_Done_Face(font->face);
114                 MEM_freeN(font);
115                 return(NULL);
116         }
117
118         font->name= BLI_strdup(name);
119         font->filename= BLI_strdup(filename);
120         blf_font_fill(font);
121         return(font);
122 }
123
124 FontBLF *blf_font_new_from_mem(char *name, unsigned char *mem, int mem_size)
125 {
126         FontBLF *font;
127         FT_Error err;
128
129         font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new_from_mem");
130         err= FT_New_Memory_Face(global_ft_lib, mem, mem_size, 0, &font->face);
131         if (err) {
132                 MEM_freeN(font);
133                 return(NULL);
134         }
135
136         err= FT_Select_Charmap(font->face, ft_encoding_unicode);
137         if (err) {
138                 printf("Can't set the unicode character map!\n");
139                 FT_Done_Face(font->face);
140                 MEM_freeN(font);
141                 return(NULL);
142         }
143
144         font->name= BLI_strdup(name);
145         font->filename= NULL;
146         blf_font_fill(font);
147         return(font);
148 }
149
150 void blf_font_size(FontBLF *font, int size, int dpi)
151 {
152         GlyphCacheBLF *gc;
153         FT_Error err;
154         
155         err= FT_Set_Char_Size(font->face, 0, (size * 64), dpi, dpi);
156         if (err) {
157                 /* FIXME: here we can go through the fixed size and choice a close one */
158                 printf("The current font don't support the size, %d and dpi, %d\n", size, dpi);
159                 return;
160         }
161
162         font->size= size;
163         font->dpi= dpi;
164
165         gc= blf_glyph_cache_find(font, size, dpi);
166         if (gc)
167                 font->glyph_cache= gc;
168         else {
169                 gc= blf_glyph_cache_new(font);
170                 if (gc)
171                         font->glyph_cache= gc;
172                 else
173                         font->glyph_cache= NULL;
174         }
175 }
176
177 void blf_font_draw(FontBLF *font, char *str)
178 {
179         unsigned int c;
180         GlyphBLF *g, *g_prev;
181         FT_Vector delta;
182         FT_UInt glyph_index;
183         int pen_x, pen_y;
184         int i, has_kerning;
185
186         i= 0;
187         pen_x= 0;
188         pen_y= 0;
189         has_kerning= FT_HAS_KERNING(font->face);
190         g_prev= NULL;
191
192         while (str[i]) {
193                 c= blf_utf8_next((unsigned char *)str, &i);
194                 if (c == 0)
195                         break;
196
197                 glyph_index= FT_Get_Char_Index(font->face, c);
198                 g= blf_glyph_search(font->glyph_cache, glyph_index);
199                 if (!g)
200                         g= blf_glyph_add(font, glyph_index, c);
201
202                 /* if we don't found a glyph, skip it. */
203                 if (!g)
204                         continue;
205
206                 if (has_kerning && g_prev) {
207                         delta.x= 0;
208                         delta.y= 0;
209
210                         FT_Get_Kerning(font->face, g_prev->index, glyph_index, FT_KERNING_UNFITTED, &delta);
211                         pen_x += delta.x >> 6;
212                 }
213
214                 blf_glyph_render(g, (float)pen_x, (float)pen_y);
215                 pen_x += g->advance;
216                 g_prev= g;
217         }
218 }
219
220 void blf_font_free(FontBLF *font)
221 {
222         GlyphCacheBLF *gc;
223
224         font->glyph_cache= NULL;
225         while (font->cache.first) {
226                 gc= font->cache.first;
227                 BLI_remlink(&font->cache, gc);
228                 blf_glyph_cache_free(gc);
229         }
230
231         FT_Done_Face(font->face);
232         if (font->filename)
233                 MEM_freeN(font->filename);
234         if (font->name)
235                 MEM_freeN(font->name);
236         MEM_freeN(font);
237 }
238
239 #endif /* WITH_FREETYPE2 */