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