f06c7fb0d28055b8f9ad947dfdbf7dc65c95b4a6
[blender.git] / source / blender / blenfont / intern / blf.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 #include <math.h>
33
34 #include <ft2build.h>
35
36 #include FT_FREETYPE_H
37 #include FT_GLYPH_H
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_listBase.h"
42 #include "DNA_vec_types.h"
43
44 #include "BKE_utildefines.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_linklist.h"       /* linknode */
48 #include "BLI_string.h"
49
50 #include "BIF_gl.h"
51 #include "BIF_glutil.h"
52 #include "BLF_api.h"
53
54 #include "blf_internal_types.h"
55 #include "blf_internal.h"
56
57
58 /* Max number of font in memory.
59  * Take care that now every font have a glyph cache per size/dpi,
60  * so we don't need load the same font with different size, just
61  * load one and call BLF_size.
62  */
63 #define BLF_MAX_FONT 16
64
65 /* Font array. */
66 FontBLF *global_font[BLF_MAX_FONT];
67
68 /* Number of font. */
69 int global_font_num= 0;
70
71 /* Current font. */
72 int global_font_cur= 0;
73
74 /* Default size and dpi, for BLF_draw_default. */
75 int global_font_default= -1;
76 int global_font_points= 11;
77 int global_font_dpi= 72;
78
79 int BLF_init(int points, int dpi)
80 {
81         int i;
82
83         for (i= 0; i < BLF_MAX_FONT; i++)
84                 global_font[i]= NULL;
85
86         global_font_points= points;
87         global_font_dpi= dpi;
88         return(blf_font_init());
89 }
90
91 void BLF_exit(void)
92 {
93         FontBLF *font;
94         int i;
95
96         for (i= 0; i < global_font_num; i++) {
97                 font= global_font[i];
98                 if (font)
99                         blf_font_free(font);
100         }
101
102         blf_font_exit();
103 }
104
105 int blf_search(char *name)
106 {
107         FontBLF *font;
108         int i;
109
110         for (i= 0; i < BLF_MAX_FONT; i++) {
111                 font= global_font[i];
112                 if (font && (!strcmp(font->name, name)))
113                         return(i);
114         }
115         return(-1);
116 }
117
118 int BLF_load(char *name)
119 {
120         FontBLF *font;
121         char *filename;
122         int i;
123
124         if (!name)
125                 return(-1);
126
127         /* check if we already load this font. */
128         i= blf_search(name);
129         if (i >= 0) {
130                 font= global_font[i];
131                 return(i);
132         }
133
134         if (global_font_num+1 >= BLF_MAX_FONT) {
135                 printf("Too many fonts!!!\n");
136                 return(-1);
137         }
138
139         filename= blf_dir_search(name);
140         if (!filename) {
141                 printf("Can't find font: %s\n", name);
142                 return(-1);
143         }
144
145         font= blf_font_new(name, filename);
146         MEM_freeN(filename);
147
148         if (!font) {
149                 printf("Can't load font: %s\n", name);
150                 return(-1);
151         }
152
153         global_font[global_font_num]= font;
154         i= global_font_num;
155         global_font_num++;
156         return(i);
157 }
158
159 void BLF_metrics_attach(unsigned char *mem, int mem_size)
160 {
161         FontBLF *font;
162
163         font= global_font[global_font_cur];
164         if (font)
165                 blf_font_attach_from_mem(font, mem, mem_size);
166 }
167
168 int BLF_load_mem(char *name, unsigned char *mem, int mem_size)
169 {
170         FontBLF *font;
171         int i;
172
173         if (!name)
174                 return(-1);
175
176         i= blf_search(name);
177         if (i >= 0) {
178                 font= global_font[i];
179                 return(i);
180         }
181
182         if (global_font_num+1 >= BLF_MAX_FONT) {
183                 printf("Too many fonts!!!\n");
184                 return(-1);
185         }
186
187         if (!mem || !mem_size) {
188                 printf("Can't load font: %s from memory!!\n", name);
189                 return(-1);
190         }
191
192         font= blf_font_new_from_mem(name, mem, mem_size);
193         if (!font) {
194                 printf("Can't load font: %s from memory!!\n", name);
195                 return(-1);
196         }
197
198         global_font[global_font_num]= font;
199         i= global_font_num;
200         global_font_num++;
201         return(i);
202 }
203
204 void BLF_set(int fontid)
205 {
206         if (fontid >= 0 && fontid < BLF_MAX_FONT)
207                 global_font_cur= fontid;
208 }
209
210 int BLF_get(void)
211 {
212         return(global_font_cur);
213 }
214
215 void BLF_enable(int option)
216 {
217         FontBLF *font;
218
219         font= global_font[global_font_cur];
220         if (font)
221                 font->flags |= option;
222 }
223
224 void BLF_disable(int option)
225 {
226         FontBLF *font;
227
228         font= global_font[global_font_cur];
229         if (font)
230                 font->flags &= ~option;
231 }
232
233 void BLF_aspect(float aspect)
234 {
235         FontBLF *font;
236
237         font= global_font[global_font_cur];
238         if (font)
239                 font->aspect= aspect;
240 }
241
242 void BLF_position(float x, float y, float z)
243 {
244         FontBLF *font;
245         float remainder;
246
247         font= global_font[global_font_cur];
248         if (font) {
249                 remainder= x - floor(x);
250                 if (remainder > 0.4 && remainder < 0.6) {
251                         if (remainder < 0.5)
252                                 x -= 0.1 * font->aspect;
253                         else
254                                 x += 0.1 * font->aspect;
255                 }
256
257                 remainder= y - floor(y);
258                 if (remainder > 0.4 && remainder < 0.6) {
259                         if (remainder < 0.5)
260                                 y -= 0.1 * font->aspect;
261                         else
262                                 y += 0.1 * font->aspect;
263                 }
264
265                 font->pos[0]= x;
266                 font->pos[1]= y;
267                 font->pos[2]= z;
268         }
269 }
270
271 void BLF_size(int size, int dpi)
272 {
273         FontBLF *font;
274
275         font= global_font[global_font_cur];
276         if (font)
277                 blf_font_size(font, size, dpi);
278 }
279
280 void BLF_blur(int size)
281 {
282         FontBLF *font;
283         
284         font= global_font[global_font_cur];
285         if (font)
286                 font->blur= size;
287 }
288
289 void BLF_draw_default(float x, float y, float z, char *str)
290 {
291         FontBLF *font;
292         int old_font, old_point, old_dpi;
293
294         if (!str)
295                 return;
296
297         if (global_font_default == -1)
298                 global_font_default= blf_search("default");
299
300         if (global_font_default == -1) {
301                 printf("Warning: Can't found default font!!\n");
302                 return;
303         }
304
305         font= global_font[global_font_cur];
306         if (font) {
307                 old_font= global_font_cur;
308                 old_point= font->size;
309                 old_dpi= font->dpi;
310         }
311
312         global_font_cur= global_font_default;
313         BLF_size(global_font_points, global_font_dpi);
314         BLF_position(x, y, z);
315         BLF_draw(str);
316
317         /* restore the old font. */
318         if (font) {
319                 global_font_cur= old_font;
320                 BLF_size(old_point, old_dpi);
321         }
322 }
323
324 void BLF_draw(char *str)
325 {
326         FontBLF *font;
327
328         /*
329          * The pixmap alignment hack is handle
330          * in BLF_position (old ui_rasterpos_safe).
331          */
332
333         font= global_font[global_font_cur];
334         if (font) {
335                 if (font->mode == BLF_MODE_BITMAP) {
336                         glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
337                         glPushAttrib(GL_ENABLE_BIT);
338                         glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
339                         glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
340                         glDisable(GL_BLEND);
341                         glRasterPos3f(font->pos[0], font->pos[1], font->pos[2]);
342
343                         blf_font_draw(font, str);
344
345                         glPopAttrib();
346                         glPopClientAttrib();
347                 }
348                 else {
349                         glEnable(GL_BLEND);
350                         glEnable(GL_TEXTURE_2D);
351                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
352
353                         glPushMatrix();
354                         glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
355                         glScalef(font->aspect, font->aspect, 1.0);
356
357                         if (font->flags & BLF_ROTATION)
358                                 glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
359
360                         blf_font_draw(font, str);
361
362                         glPopMatrix();
363                         glDisable(GL_BLEND);
364                         glDisable(GL_TEXTURE_2D);
365                 }
366         }
367 }
368
369 void BLF_boundbox(char *str, rctf *box)
370 {
371         FontBLF *font;
372
373         font= global_font[global_font_cur];
374         if (font)
375                 blf_font_boundbox(font, str, box);
376 }
377
378 float BLF_width(char *str)
379 {
380         FontBLF *font;
381
382         font= global_font[global_font_cur];
383         if (font)
384                 return(blf_font_width(font, str));
385         return(0.0f);
386 }
387
388 float BLF_width_default(char *str)
389 {
390         FontBLF *font;
391         float width;
392         int old_font, old_point, old_dpi;
393
394         if (global_font_default == -1)
395                 global_font_default= blf_search("default");
396
397         if (global_font_default == -1) {
398                 printf("Error: Can't found default font!!\n");
399                 return(0.0f);
400         }
401
402         font= global_font[global_font_cur];
403         if (font) {
404                 old_font= global_font_cur;
405                 old_point= font->size;
406                 old_dpi= font->dpi;
407         }
408
409         global_font_cur= global_font_default;
410         BLF_size(global_font_points, global_font_dpi);
411         width= BLF_width(str);
412
413         /* restore the old font. */
414         if (font) {
415                 global_font_cur= old_font;
416                 BLF_size(old_point, old_dpi);
417         }
418         return(width);
419 }
420
421 float BLF_height(char *str)
422 {
423         FontBLF *font;
424
425         font= global_font[global_font_cur];
426         if (font)
427                 return(blf_font_height(font, str));
428         return(0.0f);
429 }
430
431 float BLF_height_default(char *str)
432 {
433         FontBLF *font;
434         float height;
435         int old_font, old_point, old_dpi;
436
437         if (global_font_default == -1)
438                 global_font_default= blf_search("default");
439
440         if (global_font_default == -1) {
441                 printf("Error: Can't found default font!!\n");
442                 return(0.0f);
443         }
444
445         font= global_font[global_font_cur];
446         if (font) {
447                 old_font= global_font_cur;
448                 old_point= font->size;
449                 old_dpi= font->dpi;
450         }
451
452         global_font_cur= global_font_default;
453         BLF_size(global_font_points, global_font_dpi);
454         height= BLF_height(str);
455
456         /* restore the old font. */
457         if (font) {
458                 global_font_cur= old_font;
459                 BLF_size(old_point, old_dpi);
460         }
461         return(height);
462 }
463
464 void BLF_rotation(float angle)
465 {
466         FontBLF *font;
467
468         font= global_font[global_font_cur];
469         if (font)
470                 font->angle= angle;
471 }
472
473 void BLF_clipping(float xmin, float ymin, float xmax, float ymax)
474 {
475         FontBLF *font;
476
477         font= global_font[global_font_cur];
478         if (font) {
479                 font->clip_rec.xmin= xmin;
480                 font->clip_rec.ymin= ymin;
481                 font->clip_rec.xmax= xmax;
482                 font->clip_rec.ymax= ymax;
483         }
484 }
485
486 void BLF_mode(int mode)
487 {
488         FontBLF *font;
489
490         font= global_font[global_font_cur];
491         if (font)
492                 font->mode= mode;
493 }
494
495 void BLF_kerning(float space)
496 {
497         FontBLF *font;
498
499         font= global_font[global_font_cur];
500         if (font)
501                 font->kerning= space;
502 }