UI: Add back ability to select a custom interface font
[blender.git] / source / blender / blenfont / intern / blf.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenfont/intern/blf.c
28  *  \ingroup blf
29  *
30  * Main BlenFont (BLF) API, public functions for font handling.
31  *
32  * Wraps OpenGL and FreeType.
33  */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #include <ft2build.h>
41
42 #include FT_FREETYPE_H
43 #include FT_GLYPH_H
44
45 #include "MEM_guardedalloc.h"
46
47 #include "DNA_listBase.h"
48 #include "DNA_vec_types.h"
49
50 #include "BLI_math.h"
51 #include "BLI_threads.h"
52
53 #include "BIF_gl.h"
54 #include "BLF_api.h"
55
56 #include "blf_internal_types.h"
57 #include "blf_internal.h"
58
59 /* Max number of font in memory.
60  * Take care that now every font have a glyph cache per size/dpi,
61  * so we don't need load the same font with different size, just
62  * load one and call BLF_size.
63  */
64 #define BLF_MAX_FONT 16
65
66 /* Font array. */
67 static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
68
69 /* Default size and dpi, for BLF_draw_default. */
70 static int global_font_default = -1;
71 static int global_font_points = 11;
72 static int global_font_dpi = 72;
73
74 /* XXX, should these be made into global_font_'s too? */
75 int blf_mono_font = -1;
76 int blf_mono_font_render = -1;
77
78 static FontBLF *blf_get(int fontid)
79 {
80         if (fontid >= 0 && fontid < BLF_MAX_FONT)
81                 return global_font[fontid];
82         return NULL;
83 }
84
85 int BLF_init(int points, int dpi)
86 {
87         int i;
88
89         for (i = 0; i < BLF_MAX_FONT; i++)
90                 global_font[i] = NULL;
91
92         global_font_points = points;
93         global_font_dpi = dpi;
94         return blf_font_init();
95 }
96
97 void BLF_default_dpi(int dpi)
98 {
99         global_font_dpi = dpi;
100 }
101
102 void BLF_exit(void)
103 {
104         FontBLF *font;
105         int i;
106
107         for (i = 0; i < BLF_MAX_FONT; i++) {
108                 font = global_font[i];
109                 if (font) {
110                         blf_font_free(font);
111                         global_font[i] = NULL;
112                 }
113         }
114
115         blf_font_exit();
116 }
117
118 void BLF_cache_clear(void)
119 {
120         FontBLF *font;
121         int i;
122
123         for (i = 0; i < BLF_MAX_FONT; i++) {
124                 font = global_font[i];
125                 if (font)
126                         blf_glyph_cache_clear(font);
127         }
128 }
129
130 static int blf_search(const char *name)
131 {
132         FontBLF *font;
133         int i;
134
135         for (i = 0; i < BLF_MAX_FONT; i++) {
136                 font = global_font[i];
137                 if (font && (!strcmp(font->name, name)))
138                         return i;
139         }
140
141         return -1;
142 }
143
144 static int blf_search_available(void)
145 {
146         int i;
147
148         for (i = 0; i < BLF_MAX_FONT; i++)
149                 if (!global_font[i])
150                         return i;
151         
152         return -1;
153 }
154
155 void BLF_default_set(int fontid)
156 {
157         FontBLF *font = blf_get(fontid);
158         if (font || fontid == -1) {
159                 global_font_default = fontid;
160         }
161 }
162
163 static int blf_global_font_init(void)
164 {
165         if (global_font_default == -1) {
166                 global_font_default = blf_search("default");
167         }
168
169         if (global_font_default == -1) {
170                 printf("Warning: Can't find default font!\n");
171                 return 0;
172         }
173         else {
174                 return 1;
175         }
176 }
177
178 int BLF_load(const char *name)
179 {
180         FontBLF *font;
181         char *filename;
182         int i;
183
184         if (!name)
185                 return -1;
186
187         /* check if we already load this font. */
188         i = blf_search(name);
189         if (i >= 0) {
190                 /*font = global_font[i];*/ /*UNUSED*/
191                 return i;
192         }
193
194         i = blf_search_available();
195         if (i == -1) {
196                 printf("Too many fonts!!!\n");
197                 return -1;
198         }
199
200         filename = blf_dir_search(name);
201         if (!filename) {
202                 printf("Can't find font: %s\n", name);
203                 return -1;
204         }
205
206         font = blf_font_new(name, filename);
207         MEM_freeN(filename);
208
209         if (!font) {
210                 printf("Can't load font: %s\n", name);
211                 return -1;
212         }
213
214         global_font[i] = font;
215         return i;
216 }
217
218 int BLF_load_unique(const char *name)
219 {
220         FontBLF *font;
221         char *filename;
222         int i;
223
224         if (!name)
225                 return -1;
226
227         /* Don't search in the cache!! make a new
228          * object font, this is for keep fonts threads safe.
229          */
230         i = blf_search_available();
231         if (i == -1) {
232                 printf("Too many fonts!!!\n");
233                 return -1;
234         }
235
236         filename = blf_dir_search(name);
237         if (!filename) {
238                 printf("Can't find font: %s\n", name);
239                 return -1;
240         }
241
242         font = blf_font_new(name, filename);
243         MEM_freeN(filename);
244
245         if (!font) {
246                 printf("Can't load font: %s\n", name);
247                 return -1;
248         }
249
250         global_font[i] = font;
251         return i;
252 }
253
254 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
255 {
256         FontBLF *font = blf_get(fontid);
257
258         if (font) {
259                 blf_font_attach_from_mem(font, mem, mem_size);
260         }
261 }
262
263 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
264 {
265         FontBLF *font;
266         int i;
267
268         if (!name)
269                 return -1;
270
271         i = blf_search(name);
272         if (i >= 0) {
273                 /*font = global_font[i];*/ /*UNUSED*/
274                 return i;
275         }
276
277         i = blf_search_available();
278         if (i == -1) {
279                 printf("Too many fonts!!!\n");
280                 return -1;
281         }
282
283         if (!mem || !mem_size) {
284                 printf("Can't load font: %s from memory!!\n", name);
285                 return -1;
286         }
287
288         font = blf_font_new_from_mem(name, mem, mem_size);
289         if (!font) {
290                 printf("Can't load font: %s from memory!!\n", name);
291                 return -1;
292         }
293
294         global_font[i] = font;
295         return i;
296 }
297
298 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size)
299 {
300         FontBLF *font;
301         int i;
302
303         if (!name)
304                 return -1;
305
306         /*
307          * Don't search in the cache, make a new object font!
308          * this is to keep the font thread safe.
309          */
310         i = blf_search_available();
311         if (i == -1) {
312                 printf("Too many fonts!!!\n");
313                 return -1;
314         }
315
316         if (!mem || !mem_size) {
317                 printf("Can't load font: %s from memory!!\n", name);
318                 return -1;
319         }
320
321         font = blf_font_new_from_mem(name, mem, mem_size);
322         if (!font) {
323                 printf("Can't load font: %s from memory!!\n", name);
324                 return -1;
325         }
326
327         global_font[i] = font;
328         return i;
329 }
330
331 void BLF_unload(const char *name)
332 {
333         FontBLF *font;
334         int i;
335
336         for (i = 0; i < BLF_MAX_FONT; i++) {
337                 font = global_font[i];
338
339                 if (font && (!strcmp(font->name, name))) {
340                         blf_font_free(font);
341                         global_font[i] = NULL;
342                 }
343         }
344 }
345
346 void BLF_unload_id(int fontid)
347 {
348         FontBLF *font = blf_get(fontid);
349         if (font) {
350                 blf_font_free(font);
351                 global_font[fontid] = NULL;
352         }
353 }
354
355 void BLF_enable(int fontid, int option)
356 {
357         FontBLF *font = blf_get(fontid);
358
359         if (font) {
360                 font->flags |= option;
361         }
362 }
363
364 void BLF_disable(int fontid, int option)
365 {
366         FontBLF *font = blf_get(fontid);
367
368         if (font) {
369                 font->flags &= ~option;
370         }
371 }
372
373 void BLF_enable_default(int option)
374 {
375         FontBLF *font = blf_get(global_font_default);
376
377         if (font) {
378                 font->flags |= option;
379         }
380 }
381
382 void BLF_disable_default(int option)
383 {
384         FontBLF *font = blf_get(global_font_default);
385
386         if (font) {
387                 font->flags &= ~option;
388         }
389 }
390
391 void BLF_aspect(int fontid, float x, float y, float z)
392 {
393         FontBLF *font = blf_get(fontid);
394
395         if (font) {
396                 font->aspect[0] = x;
397                 font->aspect[1] = y;
398                 font->aspect[2] = z;
399         }
400 }
401
402 void BLF_matrix(int fontid, const double m[16])
403 {
404         FontBLF *font = blf_get(fontid);
405
406         if (font) {
407                 memcpy(font->m, m, sizeof(font->m));
408         }
409 }
410
411 void BLF_position(int fontid, float x, float y, float z)
412 {
413         FontBLF *font = blf_get(fontid);
414
415         if (font) {
416                 float xa, ya, za;
417                 float remainder;
418
419                 if (font->flags & BLF_ASPECT) {
420                         xa = font->aspect[0];
421                         ya = font->aspect[1];
422                         za = font->aspect[2];
423                 }
424                 else {
425                         xa = 1.0f;
426                         ya = 1.0f;
427                         za = 1.0f;
428                 }
429
430                 remainder = x - floorf(x);
431                 if (remainder > 0.4f && remainder < 0.6f) {
432                         if (remainder < 0.5f)
433                                 x -= 0.1f * xa;
434                         else
435                                 x += 0.1f * xa;
436                 }
437
438                 remainder = y - floorf(y);
439                 if (remainder > 0.4f && remainder < 0.6f) {
440                         if (remainder < 0.5f)
441                                 y -= 0.1f * ya;
442                         else
443                                 y += 0.1f * ya;
444                 }
445
446                 remainder = z - floorf(z);
447                 if (remainder > 0.4f && remainder < 0.6f) {
448                         if (remainder < 0.5f)
449                                 z -= 0.1f * za;
450                         else
451                                 z += 0.1f * za;
452                 }
453
454                 font->pos[0] = x;
455                 font->pos[1] = y;
456                 font->pos[2] = z;
457         }
458 }
459
460 void BLF_size(int fontid, int size, int dpi)
461 {
462         FontBLF *font = blf_get(fontid);
463
464         if (font) {
465                 blf_font_size(font, size, dpi);
466         }
467 }
468
469 void BLF_blur(int fontid, int size)
470 {
471         FontBLF *font = blf_get(fontid);
472
473         if (font) {
474                 font->blur = size;
475         }
476 }
477
478 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
479 {
480         if (!blf_global_font_init())
481                 return;
482
483         BLF_size(global_font_default, global_font_points, global_font_dpi);
484         BLF_position(global_font_default, x, y, z);
485         BLF_draw(global_font_default, str, len);
486 }
487
488 /* same as above but call 'BLF_draw_ascii' */
489 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
490 {
491         if (!blf_global_font_init())
492                 return;
493
494         BLF_size(global_font_default, global_font_points, global_font_dpi);
495         BLF_position(global_font_default, x, y, z);
496         BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
497 }
498
499 void BLF_rotation_default(float angle)
500 {
501         FontBLF *font = blf_get(global_font_default);
502
503         if (font) {
504                 font->angle = angle;
505         }
506 }
507
508 static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
509 {
510         /*
511          * The pixmap alignment hack is handle
512          * in BLF_position (old ui_rasterpos_safe).
513          */
514
515         glEnable(GL_BLEND);
516         glEnable(GL_TEXTURE_2D);
517         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
518
519         /* Save the current matrix mode. */
520         glGetIntegerv(GL_MATRIX_MODE, mode);
521
522         glMatrixMode(GL_TEXTURE);
523         glPushMatrix();
524         glLoadIdentity();
525
526         glMatrixMode(GL_MODELVIEW);
527         glPushMatrix();
528
529         if (font->flags & BLF_MATRIX)
530                 glMultMatrixd((GLdouble *)&font->m);
531
532         glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
533
534         if (font->flags & BLF_ASPECT)
535                 glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
536
537         if (font->flags & BLF_ROTATION)  /* radians -> degrees */
538                 glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
539
540         if (font->shadow || font->blur)
541                 glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
542
543         /* always bind the texture for the first glyph */
544         font->tex_bind_state = -1;
545
546         /* Save the current parameter to restore it later. */
547         glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
548         if (*param != GL_MODULATE)
549                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
550 }
551
552 static void blf_draw__end(GLint mode, GLint param)
553 {
554         /* and restore the original value. */
555         if (param != GL_MODULATE)
556                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
557
558         glMatrixMode(GL_TEXTURE);
559         glPopMatrix();
560
561         glMatrixMode(GL_MODELVIEW);
562         glPopMatrix();
563
564         if (mode != GL_MODELVIEW)
565                 glMatrixMode(mode);
566
567         glDisable(GL_BLEND);
568         glDisable(GL_TEXTURE_2D);
569 }
570
571 void BLF_draw(int fontid, const char *str, size_t len)
572 {
573         FontBLF *font = blf_get(fontid);
574         GLint mode, param;
575
576         if (font && font->glyph_cache) {
577                 blf_draw__start(font, &mode, &param);
578                 blf_font_draw(font, str, len);
579                 blf_draw__end(mode, param);
580         }
581 }
582
583 void BLF_draw_ascii(int fontid, const char *str, size_t len)
584 {
585         FontBLF *font = blf_get(fontid);
586         GLint mode, param;
587
588         if (font && font->glyph_cache) {
589                 blf_draw__start(font, &mode, &param);
590                 blf_font_draw_ascii(font, str, len);
591                 blf_draw__end(mode, param);
592         }
593 }
594
595 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
596 {
597         FontBLF *font = blf_get(fontid);
598         GLint mode, param;
599         int columns = 0;
600
601         if (font && font->glyph_cache) {
602                 blf_draw__start(font, &mode, &param);
603                 columns = blf_font_draw_mono(font, str, len, cwidth);
604                 blf_draw__end(mode, param);
605         }
606
607         return columns;
608 }
609
610 size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
611 {
612         FontBLF *font = blf_get(fontid);
613
614         if (font) {
615                 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
616                 size_t ret;
617                 ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
618                 if (r_width) {
619                         *r_width *= xa;
620                 }
621                 return ret;
622         }
623
624         if (r_width) {
625                 *r_width = 0.0f;
626         }
627         return 0;
628 }
629
630 size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
631 {
632         FontBLF *font = blf_get(fontid);
633
634         if (font) {
635                 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
636                 size_t ret;
637                 ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
638                 if (r_width) {
639                         *r_width *= xa;
640                 }
641                 return ret;
642         }
643
644         if (r_width) {
645                 *r_width = 0.0f;
646         }
647         return 0;
648 }
649
650 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
651 {
652         FontBLF *font = blf_get(fontid);
653
654         if (font) {
655                 blf_font_boundbox(font, str, len, box);
656         }
657 }
658
659 void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
660 {
661         FontBLF *font = blf_get(fontid);
662
663         if (font && font->glyph_cache) {
664                 blf_font_width_and_height(font, str, len, r_width, r_height);
665         }
666         else {
667                 *r_width = *r_height = 0.0f;
668         }
669 }
670
671 void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
672 {
673         if (!blf_global_font_init()) {
674                 *r_width = *r_height = 0.0f;
675                 return;
676         }
677
678         BLF_size(global_font_default, global_font_points, global_font_dpi);
679         BLF_width_and_height(global_font_default, str, len, r_width, r_height);
680 }
681
682 float BLF_width(int fontid, const char *str, size_t len)
683 {
684         FontBLF *font = blf_get(fontid);
685
686         if (font && font->glyph_cache) {
687                 return blf_font_width(font, str, len);
688         }
689
690         return 0.0f;
691 }
692
693 float BLF_fixed_width(int fontid)
694 {
695         FontBLF *font = blf_get(fontid);
696
697         if (font && font->glyph_cache) {
698                 return blf_font_fixed_width(font);
699         }
700
701         return 0.0f;
702 }
703
704 float BLF_width_default(const char *str, size_t len)
705 {
706         if (!blf_global_font_init())
707                 return 0.0f;
708
709         BLF_size(global_font_default, global_font_points, global_font_dpi);
710         return BLF_width(global_font_default, str, len);
711 }
712
713 float BLF_height(int fontid, const char *str, size_t len)
714 {
715         FontBLF *font = blf_get(fontid);
716
717         if (font && font->glyph_cache) {
718                 return blf_font_height(font, str, len);
719         }
720
721         return 0.0f;
722 }
723
724 float BLF_height_max(int fontid)
725 {
726         FontBLF *font = blf_get(fontid);
727
728         if (font && font->glyph_cache) {
729                 return font->glyph_cache->max_glyph_height;
730         }
731
732         return 0.0f;
733 }
734
735 float BLF_width_max(int fontid)
736 {
737         FontBLF *font = blf_get(fontid);
738
739         if (font && font->glyph_cache) {
740                 return font->glyph_cache->max_glyph_width;
741         }
742
743         return 0.0f;
744 }
745
746 float BLF_descender(int fontid)
747 {
748         FontBLF *font = blf_get(fontid);
749
750         if (font && font->glyph_cache) {
751                 return font->glyph_cache->descender;
752         }
753
754         return 0.0f;
755 }
756
757 float BLF_ascender(int fontid)
758 {
759         FontBLF *font = blf_get(fontid);
760
761         if (font && font->glyph_cache) {
762                 return font->glyph_cache->ascender;
763         }
764
765         return 0.0f;
766 }
767
768 float BLF_height_default(const char *str, size_t len)
769 {
770         if (!blf_global_font_init())
771                 return 0.0f;
772
773         BLF_size(global_font_default, global_font_points, global_font_dpi);
774
775         return BLF_height(global_font_default, str, len);
776 }
777
778 void BLF_rotation(int fontid, float angle)
779 {
780         FontBLF *font = blf_get(fontid);
781
782         if (font) {
783                 font->angle = angle;
784         }
785 }
786
787 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
788 {
789         FontBLF *font = blf_get(fontid);
790
791         if (font) {
792                 font->clip_rec.xmin = xmin;
793                 font->clip_rec.ymin = ymin;
794                 font->clip_rec.xmax = xmax;
795                 font->clip_rec.ymax = ymax;
796         }
797 }
798
799 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
800 {
801         FontBLF *font = blf_get(global_font_default);
802
803         if (font) {
804                 font->clip_rec.xmin = xmin;
805                 font->clip_rec.ymin = ymin;
806                 font->clip_rec.xmax = xmax;
807                 font->clip_rec.ymax = ymax;
808         }
809 }
810
811 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
812 {
813         FontBLF *font = blf_get(fontid);
814
815         if (font) {
816                 font->shadow = level;
817                 font->shadow_col[0] = r;
818                 font->shadow_col[1] = g;
819                 font->shadow_col[2] = b;
820                 font->shadow_col[3] = a;
821         }
822 }
823
824 void BLF_shadow_offset(int fontid, int x, int y)
825 {
826         FontBLF *font = blf_get(fontid);
827
828         if (font) {
829                 font->shadow_x = x;
830                 font->shadow_y = y;
831         }
832 }
833
834 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
835 {
836         FontBLF *font = blf_get(fontid);
837
838         if (font) {
839                 font->buf_info.fbuf = fbuf;
840                 font->buf_info.cbuf = cbuf;
841                 font->buf_info.w = w;
842                 font->buf_info.h = h;
843                 font->buf_info.ch = nch;
844                 font->buf_info.display = display;
845         }
846 }
847
848 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
849 {
850         FontBLF *font = blf_get(fontid);
851
852         if (font) {
853                 font->buf_info.col[0] = r;
854                 font->buf_info.col[1] = g;
855                 font->buf_info.col[2] = b;
856                 font->buf_info.col[3] = a;
857         }
858 }
859
860 void BLF_draw_buffer(int fontid, const char *str)
861 {
862         FontBLF *font = blf_get(fontid);
863
864         if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
865                 blf_font_buffer(font, str);
866         }
867 }
868
869 #ifdef DEBUG
870 void BLF_state_print(int fontid)
871 {
872         FontBLF *font = blf_get(fontid);
873         if (font) {
874                 printf("fontid %d %p\n", fontid, (void *)font);
875                 printf("  name:    '%s'\n", font->name);
876                 printf("  size:     %u\n", font->size);
877                 printf("  dpi:      %u\n", font->dpi);
878                 printf("  pos:      %.6f %.6f %.6f\n", UNPACK3(font->pos));
879                 printf("  aspect:   (%d) %.6f %.6f %.6f\n", (font->flags & BLF_ROTATION) != 0, UNPACK3(font->aspect));
880                 printf("  angle:    (%d) %.6f\n", (font->flags & BLF_ASPECT) != 0, font->angle);
881                 printf("  flag:     %d\n", font->flags);
882         }
883         else {
884                 printf("fontid %d (NULL)\n", fontid);
885         }
886         fflush(stdout);
887 }
888 #endif