Improvements to bmesh edge rotate
[blender-staging.git] / source / blender / blenfont / intern / blf.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenfont/intern/blf.c
28  *  \ingroup blf
29  */
30
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include <ft2build.h>
38
39 #include FT_FREETYPE_H
40 #include FT_GLYPH_H
41
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_listBase.h"
45 #include "DNA_vec_types.h"
46
47 #include "BIF_gl.h"
48 #include "BLF_api.h"
49
50 #include "blf_internal_types.h"
51 #include "blf_internal.h"
52
53
54 /* Max number of font in memory.
55  * Take care that now every font have a glyph cache per size/dpi,
56  * so we don't need load the same font with different size, just
57  * load one and call BLF_size.
58  */
59 #define BLF_MAX_FONT 16
60
61 /* Font array. */
62 static FontBLF *global_font[BLF_MAX_FONT] = {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 < BLF_MAX_FONT; i++) {
98                 font= global_font[i];
99                 if (font) {
100                         blf_font_free(font);
101                         global_font[i]= NULL;
102                 }
103         }
104
105         blf_font_exit();
106 }
107
108 void BLF_cache_clear(void)
109 {
110         FontBLF *font;
111         int i;
112
113         for (i= 0; i < BLF_MAX_FONT; i++) {
114                 font= global_font[i];
115                 if (font)
116                         blf_glyph_cache_clear(font);
117         }
118 }
119
120 static int blf_search(const char *name)
121 {
122         FontBLF *font;
123         int i;
124
125         for (i= 0; i < BLF_MAX_FONT; i++) {
126                 font= global_font[i];
127                 if (font && (!strcmp(font->name, name)))
128                         return i;
129         }
130
131         return -1;
132 }
133
134 static int blf_search_available(void)
135 {
136         int i;
137
138         for (i= 0; i < BLF_MAX_FONT; i++)
139                 if(!global_font[i])
140                         return i;
141         
142         return -1;
143 }
144
145 int BLF_load(const char *name)
146 {
147         FontBLF *font;
148         char *filename;
149         int i;
150
151         if (!name)
152                 return -1;
153
154         /* check if we already load this font. */
155         i= blf_search(name);
156         if (i >= 0) {
157                 /*font= global_font[i];*/ /*UNUSED*/
158                 return i;
159         }
160
161         i = blf_search_available();
162         if (i == -1) {
163                 printf("Too many fonts!!!\n");
164                 return -1;
165         }
166
167         filename= blf_dir_search(name);
168         if (!filename) {
169                 printf("Can't find font: %s\n", name);
170                 return -1;
171         }
172
173         font= blf_font_new(name, filename);
174         MEM_freeN(filename);
175
176         if (!font) {
177                 printf("Can't load font: %s\n", name);
178                 return -1;
179         }
180
181         global_font[i]= font;
182         return i;
183 }
184
185 int BLF_load_unique(const char *name)
186 {
187         FontBLF *font;
188         char *filename;
189         int i;
190
191         if (!name)
192                 return -1;
193
194         /* Don't search in the cache!! make a new
195          * object font, this is for keep fonts threads safe.
196          */
197         i = blf_search_available();
198         if (i == -1) {
199                 printf("Too many fonts!!!\n");
200                 return -1;
201         }
202
203         filename= blf_dir_search(name);
204         if (!filename) {
205                 printf("Can't find font: %s\n", name);
206                 return -1;
207         }
208
209         font= blf_font_new(name, filename);
210         MEM_freeN(filename);
211
212         if (!font) {
213                 printf("Can't load font: %s\n", name);
214                 return -1;
215         }
216
217         global_font[i]= font;
218         return i;
219 }
220
221 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
222 {
223         FontBLF *font= BLF_get(fontid);
224
225         if (font) {
226                 blf_font_attach_from_mem(font, mem, mem_size);
227         }
228 }
229
230 int BLF_load_mem(const char *name, unsigned char *mem, int mem_size)
231 {
232         FontBLF *font;
233         int i;
234
235         if (!name)
236                 return -1;
237
238         i= blf_search(name);
239         if (i >= 0) {
240                 /*font= global_font[i];*/ /*UNUSED*/
241                 return i;
242         }
243
244         i = blf_search_available();
245         if (i == -1) {
246                 printf("Too many fonts!!!\n");
247                 return -1;
248         }
249
250         if (!mem || !mem_size) {
251                 printf("Can't load font: %s from memory!!\n", name);
252                 return -1;
253         }
254
255         font= blf_font_new_from_mem(name, mem, mem_size);
256         if (!font) {
257                 printf("Can't load font: %s from memory!!\n", name);
258                 return -1;
259         }
260
261         global_font[i]= font;
262         return i;
263 }
264
265 int BLF_load_mem_unique(const char *name, unsigned char *mem, int mem_size)
266 {
267         FontBLF *font;
268         int i;
269
270         if (!name)
271                 return -1;
272
273         /*
274          * Don't search in the cache, make a new object font!
275          * this is to keep the font thread safe.
276          */
277         i = blf_search_available();
278         if (i == -1) {
279                 printf("Too many fonts!!!\n");
280                 return -1;
281         }
282
283         if (!mem || !mem_size) {
284                 printf("Can't load font: %s from memory!!\n", name);
285                 return -1;
286         }
287
288         font= blf_font_new_from_mem(name, mem, mem_size);
289         if (!font) {
290                 printf("Can't load font: %s from memory!!\n", name);
291                 return -1;
292         }
293
294         global_font[i]= font;
295         return i;
296 }
297
298 void BLF_unload(const char *name)
299 {
300         FontBLF *font;
301         int i;
302
303         for (i= 0; i < BLF_MAX_FONT; i++) {
304                 font= global_font[i];
305
306                 if (font && (!strcmp(font->name, name))) {
307                         blf_font_free(font);
308                         global_font[i]= NULL;
309                 }
310         }
311 }
312
313 void BLF_enable(int fontid, int option)
314 {
315         FontBLF *font= BLF_get(fontid);
316
317         if (font) {
318                 font->flags |= option;
319         }
320 }
321
322 void BLF_disable(int fontid, int option)
323 {
324         FontBLF *font= BLF_get(fontid);
325
326         if (font) {
327                 font->flags &= ~option;
328         }
329 }
330
331 void BLF_enable_default(int option)
332 {
333         FontBLF *font= BLF_get(global_font_default);
334
335         if (font) {
336                 font->flags |= option;
337         }
338 }
339
340 void BLF_disable_default(int option)
341 {
342         FontBLF *font= BLF_get(global_font_default);
343
344         if (font) {
345                 font->flags &= ~option;
346         }
347 }
348
349 void BLF_aspect(int fontid, float x, float y, float z)
350 {
351         FontBLF *font= BLF_get(fontid);
352
353         if (font) {
354                 font->aspect[0]= x;
355                 font->aspect[1]= y;
356                 font->aspect[2]= z;
357         }
358 }
359
360 void BLF_matrix(int fontid, const double m[16])
361 {
362         FontBLF *font= BLF_get(fontid);
363
364         if (font) {
365                 memcpy(font->m, m, sizeof(font->m));
366         }
367 }
368
369 void BLF_position(int fontid, float x, float y, float z)
370 {
371         FontBLF *font= BLF_get(fontid);
372
373         if (font) {
374                 float xa, ya, za;
375                 float remainder;
376
377                 if (font->flags & BLF_ASPECT) {
378                         xa= font->aspect[0];
379                         ya= font->aspect[1];
380                         za= font->aspect[2];
381                 }
382                 else {
383                         xa= 1.0f;
384                         ya= 1.0f;
385                         za= 1.0f;
386                 }
387
388                 remainder= x - floorf(x);
389                 if (remainder > 0.4f && remainder < 0.6f) {
390                         if (remainder < 0.5f)
391                                 x -= 0.1f * xa;
392                         else
393                                 x += 0.1f * xa;
394                 }
395
396                 remainder= y - floorf(y);
397                 if (remainder > 0.4f && remainder < 0.6f) {
398                         if (remainder < 0.5f)
399                                 y -= 0.1f * ya;
400                         else
401                                 y += 0.1f * ya;
402                 }
403
404                 remainder= z - floorf(z);
405                 if (remainder > 0.4f && remainder < 0.6f) {
406                         if (remainder < 0.5f)
407                                 z -= 0.1f * za;
408                         else
409                                 z += 0.1f * za;
410                 }
411
412                 font->pos[0]= x;
413                 font->pos[1]= y;
414                 font->pos[2]= z;
415         }
416 }
417
418 void BLF_size(int fontid, int size, int dpi)
419 {
420         FontBLF *font= BLF_get(fontid);
421
422         if (font) {
423                 blf_font_size(font, size, dpi);
424         }
425 }
426
427 void BLF_blur(int fontid, int size)
428 {
429         FontBLF *font= BLF_get(fontid);
430
431         if (font) {
432                 font->blur= size;
433         }
434 }
435
436 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
437 {
438         if (!str)
439                 return;
440
441         if (global_font_default == -1)
442                 global_font_default= blf_search("default");
443
444         if (global_font_default == -1) {
445                 printf("Warning: Can't found default font!!\n");
446                 return;
447         }
448
449         BLF_size(global_font_default, global_font_points, global_font_dpi);
450         BLF_position(global_font_default, x, y, z);
451         BLF_draw(global_font_default, str, len);
452 }
453
454 /* same as above but call 'BLF_draw_ascii' */
455 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
456 {
457         if (!str)
458                 return;
459
460         if (global_font_default == -1)
461                 global_font_default= blf_search("default");
462
463         if (global_font_default == -1) {
464                 printf("Warning: Can't found default font!!\n");
465                 return;
466         }
467
468         BLF_size(global_font_default, global_font_points, global_font_dpi);
469         BLF_position(global_font_default, x, y, z);
470         BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
471 }
472
473 void BLF_rotation_default(float angle)
474 {
475         FontBLF *font= BLF_get(global_font_default);
476
477         if (font) {
478                 font->angle= angle;
479         }
480 }
481
482 static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
483 {
484         /*
485          * The pixmap alignment hack is handle
486          * in BLF_position (old ui_rasterpos_safe).
487          */
488
489         glEnable(GL_BLEND);
490         glEnable(GL_TEXTURE_2D);
491         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
492
493         /* Save the current matrix mode. */
494         glGetIntegerv(GL_MATRIX_MODE, mode);
495
496         glMatrixMode(GL_TEXTURE);
497         glPushMatrix();
498         glLoadIdentity();
499
500         glMatrixMode(GL_MODELVIEW);
501         glPushMatrix();
502
503         if (font->flags & BLF_MATRIX)
504                 glMultMatrixd((GLdouble *)&font->m);
505
506         glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
507
508         if (font->flags & BLF_ASPECT)
509                 glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
510
511         if (font->flags & BLF_ROTATION)
512                 glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
513
514         if(font->shadow || font->blur)
515                 glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
516
517         /* always bind the texture for the first glyph */
518         font->tex_bind_state= -1;
519
520         /* Save the current parameter to restore it later. */
521         glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
522         if (*param != GL_MODULATE)
523                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
524 }
525
526 static void blf_draw__end(GLint mode, GLint param)
527 {
528         /* and restore the original value. */
529         if (param != GL_MODULATE)
530                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
531
532         glMatrixMode(GL_TEXTURE);
533         glPopMatrix();
534
535         glMatrixMode(GL_MODELVIEW);
536         glPopMatrix();
537
538         if (mode != GL_MODELVIEW)
539                 glMatrixMode(mode);
540
541         glDisable(GL_BLEND);
542         glDisable(GL_TEXTURE_2D);
543 }
544
545 void BLF_draw(int fontid, const char *str, size_t len)
546 {
547         FontBLF *font= BLF_get(fontid);
548         GLint mode, param;
549
550         if (font && font->glyph_cache) {
551                 blf_draw__start(font, &mode, &param);
552                 blf_font_draw(font, str, len);
553                 blf_draw__end(mode, param);
554         }
555 }
556
557 void BLF_draw_ascii(int fontid, const char *str, size_t len)
558 {
559         FontBLF *font= BLF_get(fontid);
560         GLint mode, param;
561
562         if (font && font->glyph_cache) {
563                 blf_draw__start(font, &mode, &param);
564                 blf_font_draw_ascii(font, str, len);
565                 blf_draw__end(mode, param);
566         }
567 }
568
569 void BLF_boundbox(int fontid, const char *str, rctf *box)
570 {
571         FontBLF *font= BLF_get(fontid);
572
573         if (font) {
574                 blf_font_boundbox(font, str, box);
575         }
576 }
577
578 void BLF_width_and_height(int fontid, const char *str, float *width, float *height)
579 {
580         FontBLF *font= BLF_get(fontid);
581
582         if (font && font->glyph_cache) {
583                 blf_font_width_and_height(font, str, width, height);
584         }
585 }
586
587 float BLF_width(int fontid, const char *str)
588 {
589         FontBLF *font= BLF_get(fontid);
590
591         if (font && font->glyph_cache) {
592                 return blf_font_width(font, str);
593         }
594
595         return 0.0f;
596 }
597
598 float BLF_fixed_width(int fontid)
599 {
600         FontBLF *font= BLF_get(fontid);
601
602         if (font && font->glyph_cache) {
603                 return blf_font_fixed_width(font);
604         }
605
606         return 0.0f;
607 }
608
609 float BLF_width_default(const char *str)
610 {
611         if (global_font_default == -1)
612                 global_font_default= blf_search("default");
613
614         if (global_font_default == -1) {
615                 printf("Error: Can't found default font!!\n");
616                 return 0.0f;
617         }
618
619         BLF_size(global_font_default, global_font_points, global_font_dpi);
620         return BLF_width(global_font_default, str);
621 }
622
623 float BLF_height(int fontid, const char *str)
624 {
625         FontBLF *font= BLF_get(fontid);
626
627         if (font && font->glyph_cache) {
628                 return blf_font_height(font, str);
629         }
630
631         return 0.0f;
632 }
633
634 float BLF_height_max(int fontid)
635 {
636         FontBLF *font= BLF_get(fontid);
637
638         if (font && font->glyph_cache) {
639                 return font->glyph_cache->max_glyph_height;
640         }
641
642         return 0.0f;
643 }
644
645 float BLF_width_max(int fontid)
646 {
647         FontBLF *font= BLF_get(fontid);
648
649         if (font && font->glyph_cache) {
650                 return font->glyph_cache->max_glyph_width;
651         }
652
653         return 0.0f;
654 }
655
656 float BLF_descender(int fontid)
657 {
658         FontBLF *font= BLF_get(fontid);
659
660         if (font && font->glyph_cache) {
661                 return font->glyph_cache->descender;
662         }
663
664         return 0.0f;
665 }
666
667 float BLF_ascender(int fontid)
668 {
669         FontBLF *font= BLF_get(fontid);
670
671         if (font && font->glyph_cache) {
672                 return font->glyph_cache->ascender;
673         }
674
675         return 0.0f;
676 }
677
678 float BLF_height_default(const char *str)
679 {
680         if (global_font_default == -1)
681                 global_font_default= blf_search("default");
682
683         if (global_font_default == -1) {
684                 printf("Error: Can't found default font!!\n");
685                 return 0.0f;
686         }
687
688         BLF_size(global_font_default, global_font_points, global_font_dpi);
689
690         return BLF_height(global_font_default, str);
691 }
692
693 void BLF_rotation(int fontid, float angle)
694 {
695         FontBLF *font= BLF_get(fontid);
696
697         if (font) {
698                 font->angle= angle;
699         }
700 }
701
702 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
703 {
704         FontBLF *font= BLF_get(fontid);
705
706         if (font) {
707                 font->clip_rec.xmin= xmin;
708                 font->clip_rec.ymin= ymin;
709                 font->clip_rec.xmax= xmax;
710                 font->clip_rec.ymax= ymax;
711         }
712 }
713
714 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
715 {
716         FontBLF *font= BLF_get(global_font_default);
717
718         if (font) {
719                 font->clip_rec.xmin= xmin;
720                 font->clip_rec.ymin= ymin;
721                 font->clip_rec.xmax= xmax;
722                 font->clip_rec.ymax= ymax;
723         }
724 }
725
726 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
727 {
728         FontBLF *font= BLF_get(fontid);
729
730         if (font) {
731                 font->shadow= level;
732                 font->shadow_col[0]= r;
733                 font->shadow_col[1]= g;
734                 font->shadow_col[2]= b;
735                 font->shadow_col[3]= a;
736         }
737 }
738
739 void BLF_shadow_offset(int fontid, int x, int y)
740 {
741         FontBLF *font= BLF_get(fontid);
742
743         if (font) {
744                 font->shadow_x= x;
745                 font->shadow_y= y;
746         }
747 }
748
749 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch)
750 {
751         FontBLF *font= BLF_get(fontid);
752
753         if (font) {
754                 font->b_fbuf= fbuf;
755                 font->b_cbuf= cbuf;
756                 font->bw= w;
757                 font->bh= h;
758                 font->bch= nch;
759         }
760 }
761
762 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
763 {
764         FontBLF *font= BLF_get(fontid);
765
766         if (font) {
767                 font->b_col[0]= r;
768                 font->b_col[1]= g;
769                 font->b_col[2]= b;
770                 font->b_col[3]= a;
771         }
772 }
773
774 void BLF_draw_buffer(int fontid, const char *str)
775 {
776         FontBLF *font= BLF_get(fontid);
777
778         if (font && font->glyph_cache && (font->b_fbuf || font->b_cbuf)) {
779                 blf_font_buffer(font, str);
780         }
781 }