682a0aabb4f4d4cd97cc690693448a4898b8b99d
[blender-staging.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 static 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=0, old_point=0, old_dpi=0;
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_default_rotation(float angle)
325 {
326         
327         if (global_font_default>=0) {
328                 global_font[global_font_default]->angle= angle;
329                 if(angle)
330                         global_font[global_font_default]->flags |= BLF_ROTATION;
331                 else
332                         global_font[global_font_default]->flags &= ~BLF_ROTATION;
333         }
334 }
335
336 void BLF_draw(char *str)
337 {
338         FontBLF *font;
339
340         /*
341          * The pixmap alignment hack is handle
342          * in BLF_position (old ui_rasterpos_safe).
343          */
344         font= global_font[global_font_cur];
345         if (font) {
346                 glEnable(GL_BLEND);
347                 glEnable(GL_TEXTURE_2D);
348                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
349
350                 glPushMatrix();
351                 glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
352                 glScalef(font->aspect, font->aspect, 1.0);
353
354                 if (font->flags & BLF_ROTATION)
355                         glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
356
357                 blf_font_draw(font, str);
358
359                 glPopMatrix();
360                 glDisable(GL_BLEND);
361                 glDisable(GL_TEXTURE_2D);
362         }
363 }
364
365 void BLF_boundbox(char *str, rctf *box)
366 {
367         FontBLF *font;
368
369         font= global_font[global_font_cur];
370         if (font)
371                 blf_font_boundbox(font, str, box);
372 }
373
374 void BLF_width_and_height(char *str, float *width, float *height)
375 {
376         FontBLF *font;
377
378         font= global_font[global_font_cur];
379         if (font)
380                 blf_font_width_and_height(font, str, width, height);
381 }
382
383 float BLF_width(char *str)
384 {
385         FontBLF *font;
386
387         font= global_font[global_font_cur];
388         if (font)
389                 return(blf_font_width(font, str));
390         return(0.0f);
391 }
392
393 float BLF_fixed_width(void)
394 {
395         FontBLF *font;
396
397         font= global_font[global_font_cur];
398         if (font)
399                 return(blf_font_fixed_width(font));
400         return(0.0f);
401 }
402
403 float BLF_width_default(char *str)
404 {
405         FontBLF *font;
406         float width;
407         int old_font=0, old_point=0, old_dpi=0;
408
409         if (global_font_default == -1)
410                 global_font_default= blf_search("default");
411
412         if (global_font_default == -1) {
413                 printf("Error: Can't found default font!!\n");
414                 return(0.0f);
415         }
416
417         font= global_font[global_font_cur];
418         if (font) {
419                 old_font= global_font_cur;
420                 old_point= font->size;
421                 old_dpi= font->dpi;
422         }
423
424         global_font_cur= global_font_default;
425         BLF_size(global_font_points, global_font_dpi);
426         width= BLF_width(str);
427
428         /* restore the old font. */
429         if (font) {
430                 global_font_cur= old_font;
431                 BLF_size(old_point, old_dpi);
432         }
433         return(width);
434 }
435
436 float BLF_height(char *str)
437 {
438         FontBLF *font;
439
440         font= global_font[global_font_cur];
441         if (font)
442                 return(blf_font_height(font, str));
443         return(0.0f);
444 }
445
446 float BLF_height_default(char *str)
447 {
448         FontBLF *font;
449         float height;
450         int old_font=0, old_point=0, old_dpi=0;
451
452         if (global_font_default == -1)
453                 global_font_default= blf_search("default");
454
455         if (global_font_default == -1) {
456                 printf("Error: Can't found default font!!\n");
457                 return(0.0f);
458         }
459
460         font= global_font[global_font_cur];
461         if (font) {
462                 old_font= global_font_cur;
463                 old_point= font->size;
464                 old_dpi= font->dpi;
465         }
466
467         global_font_cur= global_font_default;
468         BLF_size(global_font_points, global_font_dpi);
469         height= BLF_height(str);
470
471         /* restore the old font. */
472         if (font) {
473                 global_font_cur= old_font;
474                 BLF_size(old_point, old_dpi);
475         }
476         return(height);
477 }
478
479 void BLF_rotation(float angle)
480 {
481         FontBLF *font;
482
483         font= global_font[global_font_cur];
484         if (font)
485                 font->angle= angle;
486 }
487
488 void BLF_clipping(float xmin, float ymin, float xmax, float ymax)
489 {
490         FontBLF *font;
491
492         font= global_font[global_font_cur];
493         if (font) {
494                 font->clip_rec.xmin= xmin;
495                 font->clip_rec.ymin= ymin;
496                 font->clip_rec.xmax= xmax;
497                 font->clip_rec.ymax= ymax;
498         }
499 }
500
501 void BLF_shadow(int level, float r, float g, float b, float a)
502 {
503         FontBLF *font;
504
505         font= global_font[global_font_cur];
506         if (font) {
507                 font->shadow= level;
508                 font->shadow_col[0]= r;
509                 font->shadow_col[1]= g;
510                 font->shadow_col[2]= b;
511                 font->shadow_col[3]= a;
512         }
513 }
514
515 void BLF_shadow_offset(int x, int y)
516 {
517         FontBLF *font;
518
519         font= global_font[global_font_cur];
520         if (font) {
521                 font->shadow_x= x;
522                 font->shadow_y= y;
523         }
524 }
525
526 void BLF_buffer(float *fbuf, unsigned char *cbuf, unsigned int w, unsigned int h, int nch)
527 {
528         FontBLF *font;
529
530         font= global_font[global_font_cur];
531         if (font) {
532                 font->b_fbuf= fbuf;
533                 font->b_cbuf= cbuf;
534                 font->bw= w;
535                 font->bh= h;
536                 font->bch= nch;
537         }
538 }
539
540 void BLF_buffer_col(float r, float g, float b, float a)
541 {
542         FontBLF *font;
543
544         font= global_font[global_font_cur];
545         if (font) {
546                 font->b_col[0]= r;
547                 font->b_col[1]= g;
548                 font->b_col[2]= b;
549                 font->b_col[3]= a;
550         }
551 }
552
553 void BLF_draw_buffer(char *str)
554 {
555         FontBLF *font;
556
557         font= global_font[global_font_cur];
558         if (font)
559                 blf_font_buffer(font, str);
560 }