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