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