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