Blenfont: add BLF_unload function to unload/reload fonts.
[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., 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 /** \file blender/blenfont/intern/blf.c
30  *  \ingroup blf
31  */
32
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <math.h>
38
39 #include <ft2build.h>
40
41 #include FT_FREETYPE_H
42 #include FT_GLYPH_H
43
44 #include "MEM_guardedalloc.h"
45
46 #include "DNA_listBase.h"
47 #include "DNA_vec_types.h"
48
49 #include "BIF_gl.h"
50 #include "BLF_api.h"
51
52 #include "blf_internal_types.h"
53 #include "blf_internal.h"
54
55
56 /* Max number of font in memory.
57  * Take care that now every font have a glyph cache per size/dpi,
58  * so we don't need load the same font with different size, just
59  * load one and call BLF_size.
60  */
61 #define BLF_MAX_FONT 16
62
63 /* Font array. */
64 static FontBLF *global_font[BLF_MAX_FONT] = {0};
65
66 /* Default size and dpi, for BLF_draw_default. */
67 static int global_font_default= -1;
68 static int global_font_points= 11;
69 static int global_font_dpi= 72;
70
71 // XXX, should these be made into global_font_'s too?
72 int blf_mono_font= -1;
73 int blf_mono_font_render= -1;
74
75 static FontBLF *BLF_get(int fontid)
76 {
77         if (fontid >= 0 && fontid < BLF_MAX_FONT)
78                 return global_font[fontid];
79         return NULL;
80 }
81
82 int BLF_init(int points, int dpi)
83 {
84         int i;
85
86         for (i= 0; i < BLF_MAX_FONT; i++)
87                 global_font[i]= NULL;
88
89         global_font_points= points;
90         global_font_dpi= dpi;
91         return blf_font_init();
92 }
93
94 void BLF_exit(void)
95 {
96         FontBLF *font;
97         int i;
98
99         for (i= 0; i < BLF_MAX_FONT; i++) {
100                 font= global_font[i];
101                 if (font) {
102                         blf_font_free(font);
103                         global_font[i]= NULL;
104                 }
105         }
106
107         blf_font_exit();
108 }
109
110 void BLF_cache_clear(void)
111 {
112         FontBLF *font;
113         int i;
114
115         for (i= 0; i < BLF_MAX_FONT; i++) {
116                 font= global_font[i];
117                 if (font)
118                         blf_glyph_cache_clear(font);
119         }
120 }
121
122 static int blf_search(const char *name)
123 {
124         FontBLF *font;
125         int i;
126
127         for (i= 0; i < BLF_MAX_FONT; i++) {
128                 font= global_font[i];
129                 if (font && (!strcmp(font->name, name)))
130                         return i;
131         }
132
133         return -1;
134 }
135
136 static int blf_search_available(void)
137 {
138         int i;
139
140         for (i= 0; i < BLF_MAX_FONT; i++)
141                 if(!global_font[i])
142                         return i;
143         
144         return -1;
145 }
146
147 int BLF_load(const char *name)
148 {
149         FontBLF *font;
150         char *filename;
151         int i;
152
153         if (!name)
154                 return -1;
155
156         /* check if we already load this font. */
157         i= blf_search(name);
158         if (i >= 0) {
159                 /*font= global_font[i];*/ /*UNUSED*/
160                 return i;
161         }
162
163         i = blf_search_available();
164         if (i == -1) {
165                 printf("Too many fonts!!!\n");
166                 return -1;
167         }
168
169         filename= blf_dir_search(name);
170         if (!filename) {
171                 printf("Can't find font: %s\n", name);
172                 return -1;
173         }
174
175         font= blf_font_new(name, filename);
176         MEM_freeN(filename);
177
178         if (!font) {
179                 printf("Can't load font: %s\n", name);
180                 return -1;
181         }
182
183         global_font[i]= font;
184         return i;
185 }
186
187 int BLF_load_unique(const char *name)
188 {
189         FontBLF *font;
190         char *filename;
191         int i;
192
193         if (!name)
194                 return -1;
195
196         /* Don't search in the cache!! make a new
197          * object font, this is for keep fonts threads safe.
198          */
199         i = blf_search_available();
200         if (i == -1) {
201                 printf("Too many fonts!!!\n");
202                 return -1;
203         }
204
205         filename= blf_dir_search(name);
206         if (!filename) {
207                 printf("Can't find font: %s\n", name);
208                 return -1;
209         }
210
211         font= blf_font_new(name, filename);
212         MEM_freeN(filename);
213
214         if (!font) {
215                 printf("Can't load font: %s\n", name);
216                 return -1;
217         }
218
219         global_font[i]= font;
220         return i;
221 }
222
223 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
224 {
225         FontBLF *font= BLF_get(fontid);
226
227         if (font) {
228                 blf_font_attach_from_mem(font, mem, mem_size);
229         }
230 }
231
232 int BLF_load_mem(const char *name, unsigned char *mem, int mem_size)
233 {
234         FontBLF *font;
235         int i;
236
237         if (!name)
238                 return -1;
239
240         i= blf_search(name);
241         if (i >= 0) {
242                 /*font= global_font[i];*/ /*UNUSED*/
243                 return i;
244         }
245
246         i = blf_search_available();
247         if (i == -1) {
248                 printf("Too many fonts!!!\n");
249                 return -1;
250         }
251
252         if (!mem || !mem_size) {
253                 printf("Can't load font: %s from memory!!\n", name);
254                 return -1;
255         }
256
257         font= blf_font_new_from_mem(name, mem, mem_size);
258         if (!font) {
259                 printf("Can't load font: %s from memory!!\n", name);
260                 return -1;
261         }
262
263         global_font[i]= font;
264         return i;
265 }
266
267 int BLF_load_mem_unique(const char *name, unsigned char *mem, int mem_size)
268 {
269         FontBLF *font;
270         int i;
271
272         if (!name)
273                 return -1;
274
275         /*
276          * Don't search in the cache, make a new object font!
277          * this is to keep the font thread safe.
278          */
279         i = blf_search_available();
280         if (i == -1) {
281                 printf("Too many fonts!!!\n");
282                 return -1;
283         }
284
285         if (!mem || !mem_size) {
286                 printf("Can't load font: %s from memory!!\n", name);
287                 return -1;
288         }
289
290         font= blf_font_new_from_mem(name, mem, mem_size);
291         if (!font) {
292                 printf("Can't load font: %s from memory!!\n", name);
293                 return -1;
294         }
295
296         global_font[i]= font;
297         return i;
298 }
299
300 void BLF_unload(const char *name)
301 {
302         FontBLF *font;
303         int i;
304
305         for (i= 0; i < BLF_MAX_FONT; i++) {
306                 font= global_font[i];
307
308                 if (font && (!strcmp(font->name, name))) {
309                         blf_font_free(font);
310                         global_font[i]= NULL;
311                 }
312         }
313 }
314
315 void BLF_enable(int fontid, int option)
316 {
317         FontBLF *font= BLF_get(fontid);
318
319         if (font) {
320                 font->flags |= option;
321         }
322 }
323
324 void BLF_disable(int fontid, int option)
325 {
326         FontBLF *font= BLF_get(fontid);
327
328         if (font) {
329                 font->flags &= ~option;
330         }
331 }
332
333 void BLF_enable_default(int option)
334 {
335         FontBLF *font= BLF_get(global_font_default);
336
337         if (font) {
338                 font->flags |= option;
339         }
340 }
341
342 void BLF_disable_default(int option)
343 {
344         FontBLF *font= BLF_get(global_font_default);
345
346         if (font) {
347                 font->flags &= ~option;
348         }
349 }
350
351 void BLF_aspect(int fontid, float x, float y, float z)
352 {
353         FontBLF *font= BLF_get(fontid);
354
355         if (font) {
356                 font->aspect[0]= x;
357                 font->aspect[1]= y;
358                 font->aspect[2]= z;
359         }
360 }
361
362 void BLF_matrix(int fontid, const double m[16])
363 {
364         FontBLF *font= BLF_get(fontid);
365
366         if (font) {
367                 memcpy(font->m, m, sizeof(font->m));
368         }
369 }
370
371 void BLF_position(int fontid, float x, float y, float z)
372 {
373         FontBLF *font= BLF_get(fontid);
374
375         if (font) {
376                 float xa, ya, za;
377                 float remainder;
378
379                 if (font->flags & BLF_ASPECT) {
380                         xa= font->aspect[0];
381                         ya= font->aspect[1];
382                         za= font->aspect[2];
383                 }
384                 else {
385                         xa= 1.0f;
386                         ya= 1.0f;
387                         za= 1.0f;
388                 }
389
390                 remainder= x - floorf(x);
391                 if (remainder > 0.4f && remainder < 0.6f) {
392                         if (remainder < 0.5f)
393                                 x -= 0.1f * xa;
394                         else
395                                 x += 0.1f * xa;
396                 }
397
398                 remainder= y - floorf(y);
399                 if (remainder > 0.4f && remainder < 0.6f) {
400                         if (remainder < 0.5f)
401                                 y -= 0.1f * ya;
402                         else
403                                 y += 0.1f * ya;
404                 }
405
406                 remainder= z - floorf(z);
407                 if (remainder > 0.4f && remainder < 0.6f) {
408                         if (remainder < 0.5f)
409                                 z -= 0.1f * za;
410                         else
411                                 z += 0.1f * za;
412                 }
413
414                 font->pos[0]= x;
415                 font->pos[1]= y;
416                 font->pos[2]= z;
417         }
418 }
419
420 void BLF_size(int fontid, int size, int dpi)
421 {
422         FontBLF *font= BLF_get(fontid);
423
424         if (font) {
425                 blf_font_size(font, size, dpi);
426         }
427 }
428
429 void BLF_blur(int fontid, int size)
430 {
431         FontBLF *font= BLF_get(fontid);
432
433         if (font) {
434                 font->blur= size;
435         }
436 }
437
438 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
439 {
440         if (!str)
441                 return;
442
443         if (global_font_default == -1)
444                 global_font_default= blf_search("default");
445
446         if (global_font_default == -1) {
447                 printf("Warning: Can't found default font!!\n");
448                 return;
449         }
450
451         BLF_size(global_font_default, global_font_points, global_font_dpi);
452         BLF_position(global_font_default, x, y, z);
453         BLF_draw(global_font_default, str, len);
454 }
455
456 /* same as above but call 'BLF_draw_ascii' */
457 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
458 {
459         if (!str)
460                 return;
461
462         if (global_font_default == -1)
463                 global_font_default= blf_search("default");
464
465         if (global_font_default == -1) {
466                 printf("Warning: Can't found default font!!\n");
467                 return;
468         }
469
470         BLF_size(global_font_default, global_font_points, global_font_dpi);
471         BLF_position(global_font_default, x, y, z);
472         BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
473 }
474
475 void BLF_rotation_default(float angle)
476 {
477         FontBLF *font= BLF_get(global_font_default);
478
479         if (font) {
480                 font->angle= angle;
481         }
482 }
483
484 static void blf_draw__start(FontBLF *font)
485 {
486         /*
487          * The pixmap alignment hack is handle
488          * in BLF_position (old ui_rasterpos_safe).
489          */
490
491         glEnable(GL_BLEND);
492         glEnable(GL_TEXTURE_2D);
493         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
494
495         glPushMatrix();
496
497         if (font->flags & BLF_MATRIX)
498                 glMultMatrixd((GLdouble *)&font->m);
499
500         glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
501
502         if (font->flags & BLF_ASPECT)
503                 glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
504
505         if (font->flags & BLF_ROTATION)
506                 glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
507
508         if(font->shadow || font->blur)
509                 glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
510
511         /* always bind the texture for the first glyph */
512         font->tex_bind_state= -1;
513
514 }
515
516 static void blf_draw__end(void)
517 {
518         glPopMatrix();
519         glDisable(GL_BLEND);
520         glDisable(GL_TEXTURE_2D);
521 }
522
523 void BLF_draw(int fontid, const char *str, size_t len)
524 {
525         FontBLF *font= BLF_get(fontid);
526
527         if (font && font->glyph_cache) {
528                 blf_draw__start(font);
529                 blf_font_draw(font, str, len);
530                 blf_draw__end();
531         }
532 }
533
534 void BLF_draw_ascii(int fontid, const char *str, size_t len)
535 {
536         FontBLF *font= BLF_get(fontid);
537
538         if (font && font->glyph_cache) {
539                 blf_draw__start(font);
540                 blf_font_draw_ascii(font, str, len);
541                 blf_draw__end();
542         }
543 }
544
545 void BLF_boundbox(int fontid, const char *str, rctf *box)
546 {
547         FontBLF *font= BLF_get(fontid);
548
549         if (font) {
550                 blf_font_boundbox(font, str, box);
551         }
552 }
553
554 void BLF_width_and_height(int fontid, const char *str, float *width, float *height)
555 {
556         FontBLF *font= BLF_get(fontid);
557
558         if (font && font->glyph_cache) {
559                 blf_font_width_and_height(font, str, width, height);
560         }
561 }
562
563 float BLF_width(int fontid, const char *str)
564 {
565         FontBLF *font= BLF_get(fontid);
566
567         if (font && font->glyph_cache) {
568                 return blf_font_width(font, str);
569         }
570
571         return 0.0f;
572 }
573
574 float BLF_fixed_width(int fontid)
575 {
576         FontBLF *font= BLF_get(fontid);
577
578         if (font && font->glyph_cache) {
579                 return blf_font_fixed_width(font);
580         }
581
582         return 0.0f;
583 }
584
585 float BLF_width_default(const char *str)
586 {
587         if (global_font_default == -1)
588                 global_font_default= blf_search("default");
589
590         if (global_font_default == -1) {
591                 printf("Error: Can't found default font!!\n");
592                 return 0.0f;
593         }
594
595         BLF_size(global_font_default, global_font_points, global_font_dpi);
596         return BLF_width(global_font_default, str);
597 }
598
599 float BLF_height(int fontid, const char *str)
600 {
601         FontBLF *font= BLF_get(fontid);
602
603         if (font && font->glyph_cache) {
604                 return blf_font_height(font, str);
605         }
606
607         return 0.0f;
608 }
609
610 float BLF_height_max(int fontid)
611 {
612         FontBLF *font= BLF_get(fontid);
613
614         if (font && font->glyph_cache) {
615                 return font->glyph_cache->max_glyph_height;
616         }
617
618         return 0.0f;
619 }
620
621 float BLF_width_max(int fontid)
622 {
623         FontBLF *font= BLF_get(fontid);
624
625         if (font && font->glyph_cache) {
626                 return font->glyph_cache->max_glyph_width;
627         }
628
629         return 0.0f;
630 }
631
632 float BLF_descender(int fontid)
633 {
634         FontBLF *font= BLF_get(fontid);
635
636         if (font && font->glyph_cache) {
637                 return font->glyph_cache->descender;
638         }
639
640         return 0.0f;
641 }
642
643 float BLF_ascender(int fontid)
644 {
645         FontBLF *font= BLF_get(fontid);
646
647         if (font && font->glyph_cache) {
648                 return font->glyph_cache->ascender;
649         }
650
651         return 0.0f;
652 }
653
654 float BLF_height_default(const char *str)
655 {
656         if (global_font_default == -1)
657                 global_font_default= blf_search("default");
658
659         if (global_font_default == -1) {
660                 printf("Error: Can't found default font!!\n");
661                 return 0.0f;
662         }
663
664         BLF_size(global_font_default, global_font_points, global_font_dpi);
665
666         return BLF_height(global_font_default, str);
667 }
668
669 void BLF_rotation(int fontid, float angle)
670 {
671         FontBLF *font= BLF_get(fontid);
672
673         if (font) {
674                 font->angle= angle;
675         }
676 }
677
678 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
679 {
680         FontBLF *font= BLF_get(fontid);
681
682         if (font) {
683                 font->clip_rec.xmin= xmin;
684                 font->clip_rec.ymin= ymin;
685                 font->clip_rec.xmax= xmax;
686                 font->clip_rec.ymax= ymax;
687         }
688 }
689
690 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
691 {
692         FontBLF *font= BLF_get(global_font_default);
693
694         if (font) {
695                 font->clip_rec.xmin= xmin;
696                 font->clip_rec.ymin= ymin;
697                 font->clip_rec.xmax= xmax;
698                 font->clip_rec.ymax= ymax;
699         }
700 }
701
702 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
703 {
704         FontBLF *font= BLF_get(fontid);
705
706         if (font) {
707                 font->shadow= level;
708                 font->shadow_col[0]= r;
709                 font->shadow_col[1]= g;
710                 font->shadow_col[2]= b;
711                 font->shadow_col[3]= a;
712         }
713 }
714
715 void BLF_shadow_offset(int fontid, int x, int y)
716 {
717         FontBLF *font= BLF_get(fontid);
718
719         if (font) {
720                 font->shadow_x= x;
721                 font->shadow_y= y;
722         }
723 }
724
725 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch)
726 {
727         FontBLF *font= BLF_get(fontid);
728
729         if (font) {
730                 font->b_fbuf= fbuf;
731                 font->b_cbuf= cbuf;
732                 font->bw= w;
733                 font->bh= h;
734                 font->bch= nch;
735         }
736 }
737
738 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
739 {
740         FontBLF *font= BLF_get(fontid);
741
742         if (font) {
743                 font->b_col[0]= r;
744                 font->b_col[1]= g;
745                 font->b_col[2]= b;
746                 font->b_col[3]= a;
747         }
748 }
749
750 void BLF_draw_buffer(int fontid, const char *str)
751 {
752         FontBLF *font= BLF_get(fontid);
753
754         if (font && font->glyph_cache && (font->b_fbuf || font->b_cbuf)) {
755                 blf_font_buffer(font, str);
756         }
757 }