BugFix:
[blender-staging.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 FontBLF *global_font[BLF_MAX_FONT];
60
61 /* Number of font. */
62 int global_font_num= 0;
63
64 /* Default size and dpi, for BLF_draw_default. */
65 int global_font_default= -1;
66 int global_font_points= 11;
67 int global_font_dpi= 72;
68
69 static FontBLF *BLF_get(int fontid)
70 {
71         if (fontid >= 0 && fontid < BLF_MAX_FONT)
72                 return(global_font[fontid]);
73         return(NULL);
74 }
75
76 int BLF_init(int points, int dpi)
77 {
78         int i;
79
80         for (i= 0; i < BLF_MAX_FONT; i++)
81                 global_font[i]= NULL;
82
83         global_font_points= points;
84         global_font_dpi= dpi;
85         return(blf_font_init());
86 }
87
88 void BLF_exit(void)
89 {
90         FontBLF *font;
91         int i;
92
93         for (i= 0; i < global_font_num; i++) {
94                 font= global_font[i];
95                 if (font)
96                         blf_font_free(font);
97         }
98
99         blf_font_exit();
100 }
101
102 static int blf_search(char *name)
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 && (!strcmp(font->name, name)))
110                         return(i);
111         }
112         return(-1);
113 }
114
115 int BLF_load(char *name)
116 {
117         FontBLF *font;
118         char *filename;
119         int i;
120
121         if (!name)
122                 return(-1);
123
124         /* check if we already load this font. */
125         i= blf_search(name);
126         if (i >= 0) {
127                 font= global_font[i];
128                 return(i);
129         }
130
131         if (global_font_num+1 >= BLF_MAX_FONT) {
132                 printf("Too many fonts!!!\n");
133                 return(-1);
134         }
135
136         filename= blf_dir_search(name);
137         if (!filename) {
138                 printf("Can't find font: %s\n", name);
139                 return(-1);
140         }
141
142         font= blf_font_new(name, filename);
143         MEM_freeN(filename);
144
145         if (!font) {
146                 printf("Can't load font: %s\n", name);
147                 return(-1);
148         }
149
150         global_font[global_font_num]= font;
151         i= global_font_num;
152         global_font_num++;
153         return(i);
154 }
155
156 int BLF_load_unique(char *name)
157 {
158         FontBLF *font;
159         char *filename;
160         int i;
161
162         if (!name)
163                 return(-1);
164
165         /* Don't search in the cache!! make a new
166          * object font, this is for keep fonts threads safe.
167          */
168         if (global_font_num+1 >= BLF_MAX_FONT) {
169                 printf("Too many fonts!!!\n");
170                 return(-1);
171         }
172
173         filename= blf_dir_search(name);
174         if (!filename) {
175                 printf("Can't find font: %s\n", name);
176                 return(-1);
177         }
178
179         font= blf_font_new(name, filename);
180         MEM_freeN(filename);
181
182         if (!font) {
183                 printf("Can't load font: %s\n", name);
184                 return(-1);
185         }
186
187         global_font[global_font_num]= font;
188         i= global_font_num;
189         global_font_num++;
190         return(i);
191 }
192
193 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
194 {
195         FontBLF *font;
196
197         font= BLF_get(fontid);
198         if (font)
199                 blf_font_attach_from_mem(font, mem, mem_size);
200 }
201
202 int BLF_load_mem(char *name, unsigned char *mem, int mem_size)
203 {
204         FontBLF *font;
205         int i;
206
207         if (!name)
208                 return(-1);
209
210         i= blf_search(name);
211         if (i >= 0) {
212                 font= global_font[i];
213                 return(i);
214         }
215
216         if (global_font_num+1 >= BLF_MAX_FONT) {
217                 printf("Too many fonts!!!\n");
218                 return(-1);
219         }
220
221         if (!mem || !mem_size) {
222                 printf("Can't load font: %s from memory!!\n", name);
223                 return(-1);
224         }
225
226         font= blf_font_new_from_mem(name, mem, mem_size);
227         if (!font) {
228                 printf("Can't load font: %s from memory!!\n", name);
229                 return(-1);
230         }
231
232         global_font[global_font_num]= font;
233         i= global_font_num;
234         global_font_num++;
235         return(i);
236 }
237
238 int BLF_load_mem_unique(char *name, unsigned char *mem, int mem_size)
239 {
240         FontBLF *font;
241         int i;
242
243         if (!name)
244                 return(-1);
245
246         /*
247          * Don't search in the cache, make a new object font!
248          * this is to keep the font thread safe.
249          */
250         if (global_font_num+1 >= BLF_MAX_FONT) {
251                 printf("Too many fonts!!!\n");
252                 return(-1);
253         }
254
255         if (!mem || !mem_size) {
256                 printf("Can't load font: %s from memory!!\n", name);
257                 return(-1);
258         }
259
260         font= blf_font_new_from_mem(name, mem, mem_size);
261         if (!font) {
262                 printf("Can't load font: %s from memory!!\n", name);
263                 return(-1);
264         }
265
266         global_font[global_font_num]= font;
267         i= global_font_num;
268         global_font_num++;
269         return(i);
270 }
271
272 void BLF_enable(int fontid, int option)
273 {
274         FontBLF *font;
275
276         font= BLF_get(fontid);
277         if (font)
278                 font->flags |= option;
279 }
280
281 void BLF_disable(int fontid, int option)
282 {
283         FontBLF *font;
284
285         font= BLF_get(fontid);
286         if (font)
287                 font->flags &= ~option;
288 }
289
290 void BLF_enable_default(int option)
291 {
292         FontBLF *font;
293
294         font= BLF_get(global_font_default);
295         if (font)
296                 font->flags |= option;
297 }
298
299 void BLF_disable_default(int option)
300 {
301         FontBLF *font;
302
303         font= BLF_get(global_font_default);
304         if (font)
305                 font->flags &= ~option;
306 }
307
308 void BLF_aspect(int fontid, float aspect)
309 {
310         FontBLF *font;
311
312         font= BLF_get(fontid);
313         if (font)
314                 font->aspect= aspect;
315 }
316
317 void BLF_position(int fontid, float x, float y, float z)
318 {
319         FontBLF *font;
320         float remainder;
321
322         font= BLF_get(fontid);
323         if (font) {
324                 remainder= x - floor(x);
325                 if (remainder > 0.4 && remainder < 0.6) {
326                         if (remainder < 0.5)
327                                 x -= 0.1 * font->aspect;
328                         else
329                                 x += 0.1 * font->aspect;
330                 }
331
332                 remainder= y - floor(y);
333                 if (remainder > 0.4 && remainder < 0.6) {
334                         if (remainder < 0.5)
335                                 y -= 0.1 * font->aspect;
336                         else
337                                 y += 0.1 * font->aspect;
338                 }
339
340                 font->pos[0]= x;
341                 font->pos[1]= y;
342                 font->pos[2]= z;
343         }
344 }
345
346 void BLF_size(int fontid, int size, int dpi)
347 {
348         FontBLF *font;
349
350         font= BLF_get(fontid);
351         if (font)
352                 blf_font_size(font, size, dpi);
353 }
354
355 void BLF_blur(int fontid, int size)
356 {
357         FontBLF *font;
358         
359         font= BLF_get(fontid);
360         if (font)
361                 font->blur= size;
362 }
363
364 void BLF_draw_default(float x, float y, float z, char *str)
365 {
366         FontBLF *font;
367         int old_font=0, old_point=0, old_dpi=0;
368
369         if (!str)
370                 return;
371
372         if (global_font_default == -1)
373                 global_font_default= blf_search("default");
374
375         if (global_font_default == -1) {
376                 printf("Warning: Can't found default font!!\n");
377                 return;
378         }
379
380         BLF_size(global_font_default, global_font_points, global_font_dpi);
381         BLF_position(global_font_default, x, y, z);
382         BLF_draw(global_font_default, str);
383 }
384
385 void BLF_rotation_default(float angle)
386 {
387         FontBLF *font;
388
389         font= BLF_get(global_font_default);
390         if (font)
391                 font->angle= angle;
392 }
393
394 void BLF_draw(int fontid, char *str)
395 {
396         FontBLF *font;
397
398         /*
399          * The pixmap alignment hack is handle
400          * in BLF_position (old ui_rasterpos_safe).
401          */
402         font= BLF_get(fontid);
403         if (font) {
404                 glEnable(GL_BLEND);
405                 glEnable(GL_TEXTURE_2D);
406                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
407
408                 glPushMatrix();
409                 glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
410                 glScalef(font->aspect, font->aspect, 1.0);
411
412                 if (font->flags & BLF_ROTATION)
413                         glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
414
415                 blf_font_draw(font, str);
416
417                 glPopMatrix();
418                 glDisable(GL_BLEND);
419                 glDisable(GL_TEXTURE_2D);
420         }
421 }
422
423 void BLF_boundbox(int fontid, char *str, rctf *box)
424 {
425         FontBLF *font;
426
427         font= BLF_get(fontid);
428         if (font)
429                 blf_font_boundbox(font, str, box);
430 }
431
432 void BLF_width_and_height(int fontid, char *str, float *width, float *height)
433 {
434         FontBLF *font;
435
436         font= BLF_get(fontid);
437         if (font)
438                 blf_font_width_and_height(font, str, width, height);
439 }
440
441 float BLF_width(int fontid, char *str)
442 {
443         FontBLF *font;
444
445         font= BLF_get(fontid);
446         if (font)
447                 return(blf_font_width(font, str));
448         return(0.0f);
449 }
450
451 float BLF_fixed_width(int fontid)
452 {
453         FontBLF *font;
454
455         font= BLF_get(fontid);
456         if (font)
457                 return(blf_font_fixed_width(font));
458         return(0.0f);
459 }
460
461 float BLF_width_default(char *str)
462 {
463         FontBLF *font;
464         float width;
465         int old_font=0, old_point=0, old_dpi=0;
466
467         if (global_font_default == -1)
468                 global_font_default= blf_search("default");
469
470         if (global_font_default == -1) {
471                 printf("Error: Can't found default font!!\n");
472                 return(0.0f);
473         }
474
475         BLF_size(global_font_default, global_font_points, global_font_dpi);
476         width= BLF_width(global_font_default, str);
477
478         return(width);
479 }
480
481 float BLF_height(int fontid, char *str)
482 {
483         FontBLF *font;
484
485         font= BLF_get(fontid);
486         if (font)
487                 return(blf_font_height(font, str));
488         return(0.0f);
489 }
490
491 float BLF_height_default(char *str)
492 {
493         FontBLF *font;
494         float height;
495         int old_font=0, old_point=0, old_dpi=0;
496
497         if (global_font_default == -1)
498                 global_font_default= blf_search("default");
499
500         if (global_font_default == -1) {
501                 printf("Error: Can't found default font!!\n");
502                 return(0.0f);
503         }
504
505         BLF_size(global_font_default, global_font_points, global_font_dpi);
506         height= BLF_height(global_font_default, str);
507
508         return(height);
509 }
510
511 void BLF_rotation(int fontid, float angle)
512 {
513         FontBLF *font;
514
515         font= BLF_get(fontid);
516         if (font)
517                 font->angle= angle;
518 }
519
520 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
521 {
522         FontBLF *font;
523
524         font= BLF_get(fontid);
525         if (font) {
526                 font->clip_rec.xmin= xmin;
527                 font->clip_rec.ymin= ymin;
528                 font->clip_rec.xmax= xmax;
529                 font->clip_rec.ymax= ymax;
530         }
531 }
532
533 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
534 {
535         FontBLF *font;
536
537         font= BLF_get(global_font_default);
538         if (font) {
539                 font->clip_rec.xmin= xmin;
540                 font->clip_rec.ymin= ymin;
541                 font->clip_rec.xmax= xmax;
542                 font->clip_rec.ymax= ymax;
543         }
544 }
545
546 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
547 {
548         FontBLF *font;
549
550         font= BLF_get(fontid);
551         if (font) {
552                 font->shadow= level;
553                 font->shadow_col[0]= r;
554                 font->shadow_col[1]= g;
555                 font->shadow_col[2]= b;
556                 font->shadow_col[3]= a;
557         }
558 }
559
560 void BLF_shadow_offset(int fontid, int x, int y)
561 {
562         FontBLF *font;
563
564         font= BLF_get(fontid);
565         if (font) {
566                 font->shadow_x= x;
567                 font->shadow_y= y;
568         }
569 }
570
571 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, unsigned int w, unsigned int h, int nch)
572 {
573         FontBLF *font;
574
575         font= BLF_get(fontid);
576         if (font) {
577                 font->b_fbuf= fbuf;
578                 font->b_cbuf= cbuf;
579                 font->bw= w;
580                 font->bh= h;
581                 font->bch= nch;
582         }
583 }
584
585 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
586 {
587         FontBLF *font;
588
589         font= BLF_get(fontid);
590         if (font) {
591                 font->b_col[0]= r;
592                 font->b_col[1]= g;
593                 font->b_col[2]= b;
594                 font->b_col[3]= a;
595         }
596 }
597
598 void BLF_draw_buffer(int fontid, char *str)
599 {
600         FontBLF *font;
601
602         font= BLF_get(fontid);
603         if (font)
604                 blf_font_buffer(font, str);
605 }