2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2009 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/blenfont/intern/blf.c
30 * Main BlenFont (BLF) API, public functions for font handling.
32 * Wraps OpenGL and FreeType.
42 #include FT_FREETYPE_H
45 #include "MEM_guardedalloc.h"
47 #include "DNA_listBase.h"
48 #include "DNA_vec_types.h"
51 #include "BLI_threads.h"
56 #include "blf_internal_types.h"
57 #include "blf_internal.h"
59 /* Max number of font in memory.
60 * Take care that now every font have a glyph cache per size/dpi,
61 * so we don't need load the same font with different size, just
62 * load one and call BLF_size.
64 #define BLF_MAX_FONT 16
67 static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
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;
74 /* XXX, should these be made into global_font_'s too? */
75 int blf_mono_font = -1;
76 int blf_mono_font_render = -1;
78 static FontBLF *blf_get(int fontid)
80 if (fontid >= 0 && fontid < BLF_MAX_FONT)
81 return global_font[fontid];
85 int BLF_init(int points, int dpi)
89 for (i = 0; i < BLF_MAX_FONT; i++)
90 global_font[i] = NULL;
92 global_font_points = points;
93 global_font_dpi = dpi;
94 return blf_font_init();
97 void BLF_default_dpi(int dpi)
99 global_font_dpi = dpi;
107 for (i = 0; i < BLF_MAX_FONT; i++) {
108 font = global_font[i];
111 global_font[i] = NULL;
118 void BLF_cache_clear(void)
123 for (i = 0; i < BLF_MAX_FONT; i++) {
124 font = global_font[i];
126 blf_glyph_cache_clear(font);
130 static int blf_search(const char *name)
135 for (i = 0; i < BLF_MAX_FONT; i++) {
136 font = global_font[i];
137 if (font && (!strcmp(font->name, name)))
144 static int blf_search_available(void)
148 for (i = 0; i < BLF_MAX_FONT; i++)
155 static int blf_global_font_init(void)
157 if (global_font_default == -1) {
158 global_font_default = blf_search("default");
161 if (global_font_default == -1) {
162 printf("Warning: Can't find default font!\n");
170 int BLF_load(const char *name)
179 /* check if we already load this font. */
180 i = blf_search(name);
182 /*font = global_font[i];*/ /*UNUSED*/
186 i = blf_search_available();
188 printf("Too many fonts!!!\n");
192 filename = blf_dir_search(name);
194 printf("Can't find font: %s\n", name);
198 font = blf_font_new(name, filename);
202 printf("Can't load font: %s\n", name);
206 global_font[i] = font;
210 int BLF_load_unique(const char *name)
219 /* Don't search in the cache!! make a new
220 * object font, this is for keep fonts threads safe.
222 i = blf_search_available();
224 printf("Too many fonts!!!\n");
228 filename = blf_dir_search(name);
230 printf("Can't find font: %s\n", name);
234 font = blf_font_new(name, filename);
238 printf("Can't load font: %s\n", name);
242 global_font[i] = font;
246 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
248 FontBLF *font = blf_get(fontid);
251 blf_font_attach_from_mem(font, mem, mem_size);
255 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
263 i = blf_search(name);
265 /*font = global_font[i];*/ /*UNUSED*/
269 i = blf_search_available();
271 printf("Too many fonts!!!\n");
275 if (!mem || !mem_size) {
276 printf("Can't load font: %s from memory!!\n", name);
280 font = blf_font_new_from_mem(name, mem, mem_size);
282 printf("Can't load font: %s from memory!!\n", name);
286 global_font[i] = font;
290 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size)
299 * Don't search in the cache, make a new object font!
300 * this is to keep the font thread safe.
302 i = blf_search_available();
304 printf("Too many fonts!!!\n");
308 if (!mem || !mem_size) {
309 printf("Can't load font: %s from memory!!\n", name);
313 font = blf_font_new_from_mem(name, mem, mem_size);
315 printf("Can't load font: %s from memory!!\n", name);
319 global_font[i] = font;
323 void BLF_unload(const char *name)
328 for (i = 0; i < BLF_MAX_FONT; i++) {
329 font = global_font[i];
331 if (font && (!strcmp(font->name, name))) {
333 global_font[i] = NULL;
338 void BLF_enable(int fontid, int option)
340 FontBLF *font = blf_get(fontid);
343 font->flags |= option;
347 void BLF_disable(int fontid, int option)
349 FontBLF *font = blf_get(fontid);
352 font->flags &= ~option;
356 void BLF_enable_default(int option)
358 FontBLF *font = blf_get(global_font_default);
361 font->flags |= option;
365 void BLF_disable_default(int option)
367 FontBLF *font = blf_get(global_font_default);
370 font->flags &= ~option;
374 void BLF_aspect(int fontid, float x, float y, float z)
376 FontBLF *font = blf_get(fontid);
385 void BLF_matrix(int fontid, const double m[16])
387 FontBLF *font = blf_get(fontid);
390 memcpy(font->m, m, sizeof(font->m));
394 void BLF_position(int fontid, float x, float y, float z)
396 FontBLF *font = blf_get(fontid);
402 if (font->flags & BLF_ASPECT) {
403 xa = font->aspect[0];
404 ya = font->aspect[1];
405 za = font->aspect[2];
413 remainder = x - floorf(x);
414 if (remainder > 0.4f && remainder < 0.6f) {
415 if (remainder < 0.5f)
421 remainder = y - floorf(y);
422 if (remainder > 0.4f && remainder < 0.6f) {
423 if (remainder < 0.5f)
429 remainder = z - floorf(z);
430 if (remainder > 0.4f && remainder < 0.6f) {
431 if (remainder < 0.5f)
443 void BLF_size(int fontid, int size, int dpi)
445 FontBLF *font = blf_get(fontid);
448 blf_font_size(font, size, dpi);
452 void BLF_blur(int fontid, int size)
454 FontBLF *font = blf_get(fontid);
461 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
463 if (!blf_global_font_init())
466 BLF_size(global_font_default, global_font_points, global_font_dpi);
467 BLF_position(global_font_default, x, y, z);
468 BLF_draw(global_font_default, str, len);
471 /* same as above but call 'BLF_draw_ascii' */
472 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
474 if (!blf_global_font_init())
477 BLF_size(global_font_default, global_font_points, global_font_dpi);
478 BLF_position(global_font_default, x, y, z);
479 BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
482 void BLF_rotation_default(float angle)
484 FontBLF *font = blf_get(global_font_default);
491 static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
494 * The pixmap alignment hack is handle
495 * in BLF_position (old ui_rasterpos_safe).
499 glEnable(GL_TEXTURE_2D);
500 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
502 /* Save the current matrix mode. */
503 glGetIntegerv(GL_MATRIX_MODE, mode);
505 glMatrixMode(GL_TEXTURE);
509 glMatrixMode(GL_MODELVIEW);
512 if (font->flags & BLF_MATRIX)
513 glMultMatrixd((GLdouble *)&font->m);
515 glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
517 if (font->flags & BLF_ASPECT)
518 glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
520 if (font->flags & BLF_ROTATION) /* radians -> degrees */
521 glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
523 if (font->shadow || font->blur)
524 glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
526 /* always bind the texture for the first glyph */
527 font->tex_bind_state = -1;
529 /* Save the current parameter to restore it later. */
530 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
531 if (*param != GL_MODULATE)
532 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
535 static void blf_draw__end(GLint mode, GLint param)
537 /* and restore the original value. */
538 if (param != GL_MODULATE)
539 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
541 glMatrixMode(GL_TEXTURE);
544 glMatrixMode(GL_MODELVIEW);
547 if (mode != GL_MODELVIEW)
551 glDisable(GL_TEXTURE_2D);
554 void BLF_draw(int fontid, const char *str, size_t len)
556 FontBLF *font = blf_get(fontid);
559 if (font && font->glyph_cache) {
560 blf_draw__start(font, &mode, ¶m);
561 blf_font_draw(font, str, len);
562 blf_draw__end(mode, param);
566 void BLF_draw_ascii(int fontid, const char *str, size_t len)
568 FontBLF *font = blf_get(fontid);
571 if (font && font->glyph_cache) {
572 blf_draw__start(font, &mode, ¶m);
573 blf_font_draw_ascii(font, str, len);
574 blf_draw__end(mode, param);
578 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
580 FontBLF *font = blf_get(fontid);
584 if (font && font->glyph_cache) {
585 blf_draw__start(font, &mode, ¶m);
586 columns = blf_font_draw_mono(font, str, len, cwidth);
587 blf_draw__end(mode, param);
593 size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
595 FontBLF *font = blf_get(fontid);
598 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
600 ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
613 size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
615 FontBLF *font = blf_get(fontid);
618 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
620 ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
633 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
635 FontBLF *font = blf_get(fontid);
638 blf_font_boundbox(font, str, len, box);
642 void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
644 FontBLF *font = blf_get(fontid);
646 if (font && font->glyph_cache) {
647 blf_font_width_and_height(font, str, len, r_width, r_height);
650 *r_width = *r_height = 0.0f;
654 void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
656 if (!blf_global_font_init()) {
657 *r_width = *r_height = 0.0f;
661 BLF_size(global_font_default, global_font_points, global_font_dpi);
662 BLF_width_and_height(global_font_default, str, len, r_width, r_height);
665 float BLF_width(int fontid, const char *str, size_t len)
667 FontBLF *font = blf_get(fontid);
669 if (font && font->glyph_cache) {
670 return blf_font_width(font, str, len);
676 float BLF_fixed_width(int fontid)
678 FontBLF *font = blf_get(fontid);
680 if (font && font->glyph_cache) {
681 return blf_font_fixed_width(font);
687 float BLF_width_default(const char *str, size_t len)
689 if (!blf_global_font_init())
692 BLF_size(global_font_default, global_font_points, global_font_dpi);
693 return BLF_width(global_font_default, str, len);
696 float BLF_height(int fontid, const char *str, size_t len)
698 FontBLF *font = blf_get(fontid);
700 if (font && font->glyph_cache) {
701 return blf_font_height(font, str, len);
707 float BLF_height_max(int fontid)
709 FontBLF *font = blf_get(fontid);
711 if (font && font->glyph_cache) {
712 return font->glyph_cache->max_glyph_height;
718 float BLF_width_max(int fontid)
720 FontBLF *font = blf_get(fontid);
722 if (font && font->glyph_cache) {
723 return font->glyph_cache->max_glyph_width;
729 float BLF_descender(int fontid)
731 FontBLF *font = blf_get(fontid);
733 if (font && font->glyph_cache) {
734 return font->glyph_cache->descender;
740 float BLF_ascender(int fontid)
742 FontBLF *font = blf_get(fontid);
744 if (font && font->glyph_cache) {
745 return font->glyph_cache->ascender;
751 float BLF_height_default(const char *str, size_t len)
753 if (!blf_global_font_init())
756 BLF_size(global_font_default, global_font_points, global_font_dpi);
758 return BLF_height(global_font_default, str, len);
761 void BLF_rotation(int fontid, float angle)
763 FontBLF *font = blf_get(fontid);
770 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
772 FontBLF *font = blf_get(fontid);
775 font->clip_rec.xmin = xmin;
776 font->clip_rec.ymin = ymin;
777 font->clip_rec.xmax = xmax;
778 font->clip_rec.ymax = ymax;
782 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
784 FontBLF *font = blf_get(global_font_default);
787 font->clip_rec.xmin = xmin;
788 font->clip_rec.ymin = ymin;
789 font->clip_rec.xmax = xmax;
790 font->clip_rec.ymax = ymax;
794 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
796 FontBLF *font = blf_get(fontid);
799 font->shadow = level;
800 font->shadow_col[0] = r;
801 font->shadow_col[1] = g;
802 font->shadow_col[2] = b;
803 font->shadow_col[3] = a;
807 void BLF_shadow_offset(int fontid, int x, int y)
809 FontBLF *font = blf_get(fontid);
817 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
819 FontBLF *font = blf_get(fontid);
822 font->buf_info.fbuf = fbuf;
823 font->buf_info.cbuf = cbuf;
824 font->buf_info.w = w;
825 font->buf_info.h = h;
826 font->buf_info.ch = nch;
827 font->buf_info.display = display;
831 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
833 FontBLF *font = blf_get(fontid);
836 font->buf_info.col[0] = r;
837 font->buf_info.col[1] = g;
838 font->buf_info.col[2] = b;
839 font->buf_info.col[3] = a;
843 void BLF_draw_buffer(int fontid, const char *str)
845 FontBLF *font = blf_get(fontid);
847 if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
848 blf_font_buffer(font, str);
853 void BLF_state_print(int fontid)
855 FontBLF *font = blf_get(fontid);
857 printf("fontid %d %p\n", fontid, (void *)font);
858 printf(" name: '%s'\n", font->name);
859 printf(" size: %u\n", font->size);
860 printf(" dpi: %u\n", font->dpi);
861 printf(" pos: %.6f %.6f %.6f\n", UNPACK3(font->pos));
862 printf(" aspect: (%d) %.6f %.6f %.6f\n", (font->flags & BLF_ROTATION) != 0, UNPACK3(font->aspect));
863 printf(" angle: (%d) %.6f\n", (font->flags & BLF_ASPECT) != 0, font->angle);
864 printf(" flag: %d\n", font->flags);
867 printf("fontid %d (NULL)\n", fontid);