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