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 void BLF_default_set(int fontid)
157 FontBLF *font = blf_get(fontid);
158 if (font || fontid == -1) {
159 global_font_default = fontid;
163 static int blf_global_font_init(void)
165 if (global_font_default == -1) {
166 global_font_default = blf_search("default");
169 if (global_font_default == -1) {
170 printf("Warning: Can't find default font!\n");
178 int BLF_load(const char *name)
187 /* check if we already load this font. */
188 i = blf_search(name);
190 /*font = global_font[i];*/ /*UNUSED*/
194 i = blf_search_available();
196 printf("Too many fonts!!!\n");
200 filename = blf_dir_search(name);
202 printf("Can't find font: %s\n", name);
206 font = blf_font_new(name, filename);
210 printf("Can't load font: %s\n", name);
214 global_font[i] = font;
218 int BLF_load_unique(const char *name)
227 /* Don't search in the cache!! make a new
228 * object font, this is for keep fonts threads safe.
230 i = blf_search_available();
232 printf("Too many fonts!!!\n");
236 filename = blf_dir_search(name);
238 printf("Can't find font: %s\n", name);
242 font = blf_font_new(name, filename);
246 printf("Can't load font: %s\n", name);
250 global_font[i] = font;
254 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
256 FontBLF *font = blf_get(fontid);
259 blf_font_attach_from_mem(font, mem, mem_size);
263 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
271 i = blf_search(name);
273 /*font = global_font[i];*/ /*UNUSED*/
277 i = blf_search_available();
279 printf("Too many fonts!!!\n");
283 if (!mem || !mem_size) {
284 printf("Can't load font: %s from memory!!\n", name);
288 font = blf_font_new_from_mem(name, mem, mem_size);
290 printf("Can't load font: %s from memory!!\n", name);
294 global_font[i] = font;
298 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size)
307 * Don't search in the cache, make a new object font!
308 * this is to keep the font thread safe.
310 i = blf_search_available();
312 printf("Too many fonts!!!\n");
316 if (!mem || !mem_size) {
317 printf("Can't load font: %s from memory!!\n", name);
321 font = blf_font_new_from_mem(name, mem, mem_size);
323 printf("Can't load font: %s from memory!!\n", name);
327 global_font[i] = font;
331 void BLF_unload(const char *name)
336 for (i = 0; i < BLF_MAX_FONT; i++) {
337 font = global_font[i];
339 if (font && (!strcmp(font->name, name))) {
341 global_font[i] = NULL;
346 void BLF_unload_id(int fontid)
348 FontBLF *font = blf_get(fontid);
351 global_font[fontid] = NULL;
355 void BLF_enable(int fontid, int option)
357 FontBLF *font = blf_get(fontid);
360 font->flags |= option;
364 void BLF_disable(int fontid, int option)
366 FontBLF *font = blf_get(fontid);
369 font->flags &= ~option;
373 void BLF_enable_default(int option)
375 FontBLF *font = blf_get(global_font_default);
378 font->flags |= option;
382 void BLF_disable_default(int option)
384 FontBLF *font = blf_get(global_font_default);
387 font->flags &= ~option;
391 void BLF_aspect(int fontid, float x, float y, float z)
393 FontBLF *font = blf_get(fontid);
402 void BLF_matrix(int fontid, const double m[16])
404 FontBLF *font = blf_get(fontid);
407 memcpy(font->m, m, sizeof(font->m));
411 void BLF_position(int fontid, float x, float y, float z)
413 FontBLF *font = blf_get(fontid);
419 if (font->flags & BLF_ASPECT) {
420 xa = font->aspect[0];
421 ya = font->aspect[1];
422 za = font->aspect[2];
430 remainder = x - floorf(x);
431 if (remainder > 0.4f && remainder < 0.6f) {
432 if (remainder < 0.5f)
438 remainder = y - floorf(y);
439 if (remainder > 0.4f && remainder < 0.6f) {
440 if (remainder < 0.5f)
446 remainder = z - floorf(z);
447 if (remainder > 0.4f && remainder < 0.6f) {
448 if (remainder < 0.5f)
460 void BLF_size(int fontid, int size, int dpi)
462 FontBLF *font = blf_get(fontid);
465 blf_font_size(font, size, dpi);
469 void BLF_blur(int fontid, int size)
471 FontBLF *font = blf_get(fontid);
478 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
480 if (!blf_global_font_init())
483 BLF_size(global_font_default, global_font_points, global_font_dpi);
484 BLF_position(global_font_default, x, y, z);
485 BLF_draw(global_font_default, str, len);
488 /* same as above but call 'BLF_draw_ascii' */
489 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
491 if (!blf_global_font_init())
494 BLF_size(global_font_default, global_font_points, global_font_dpi);
495 BLF_position(global_font_default, x, y, z);
496 BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
499 void BLF_rotation_default(float angle)
501 FontBLF *font = blf_get(global_font_default);
508 static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
511 * The pixmap alignment hack is handle
512 * in BLF_position (old ui_rasterpos_safe).
516 glEnable(GL_TEXTURE_2D);
517 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
519 /* Save the current matrix mode. */
520 glGetIntegerv(GL_MATRIX_MODE, mode);
522 glMatrixMode(GL_TEXTURE);
526 glMatrixMode(GL_MODELVIEW);
529 if (font->flags & BLF_MATRIX)
530 glMultMatrixd((GLdouble *)&font->m);
532 glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
534 if (font->flags & BLF_ASPECT)
535 glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
537 if (font->flags & BLF_ROTATION) /* radians -> degrees */
538 glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
540 if (font->shadow || font->blur)
541 glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
543 /* always bind the texture for the first glyph */
544 font->tex_bind_state = -1;
546 /* Save the current parameter to restore it later. */
547 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
548 if (*param != GL_MODULATE)
549 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
552 static void blf_draw__end(GLint mode, GLint param)
554 /* and restore the original value. */
555 if (param != GL_MODULATE)
556 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
558 glMatrixMode(GL_TEXTURE);
561 glMatrixMode(GL_MODELVIEW);
564 if (mode != GL_MODELVIEW)
568 glDisable(GL_TEXTURE_2D);
571 void BLF_draw(int fontid, const char *str, size_t len)
573 FontBLF *font = blf_get(fontid);
576 if (font && font->glyph_cache) {
577 blf_draw__start(font, &mode, ¶m);
578 blf_font_draw(font, str, len);
579 blf_draw__end(mode, param);
583 void BLF_draw_ascii(int fontid, const char *str, size_t len)
585 FontBLF *font = blf_get(fontid);
588 if (font && font->glyph_cache) {
589 blf_draw__start(font, &mode, ¶m);
590 blf_font_draw_ascii(font, str, len);
591 blf_draw__end(mode, param);
595 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
597 FontBLF *font = blf_get(fontid);
601 if (font && font->glyph_cache) {
602 blf_draw__start(font, &mode, ¶m);
603 columns = blf_font_draw_mono(font, str, len, cwidth);
604 blf_draw__end(mode, param);
610 size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
612 FontBLF *font = blf_get(fontid);
615 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
617 ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
630 size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
632 FontBLF *font = blf_get(fontid);
635 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
637 ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
650 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
652 FontBLF *font = blf_get(fontid);
655 blf_font_boundbox(font, str, len, box);
659 void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
661 FontBLF *font = blf_get(fontid);
663 if (font && font->glyph_cache) {
664 blf_font_width_and_height(font, str, len, r_width, r_height);
667 *r_width = *r_height = 0.0f;
671 void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
673 if (!blf_global_font_init()) {
674 *r_width = *r_height = 0.0f;
678 BLF_size(global_font_default, global_font_points, global_font_dpi);
679 BLF_width_and_height(global_font_default, str, len, r_width, r_height);
682 float BLF_width(int fontid, const char *str, size_t len)
684 FontBLF *font = blf_get(fontid);
686 if (font && font->glyph_cache) {
687 return blf_font_width(font, str, len);
693 float BLF_fixed_width(int fontid)
695 FontBLF *font = blf_get(fontid);
697 if (font && font->glyph_cache) {
698 return blf_font_fixed_width(font);
704 float BLF_width_default(const char *str, size_t len)
706 if (!blf_global_font_init())
709 BLF_size(global_font_default, global_font_points, global_font_dpi);
710 return BLF_width(global_font_default, str, len);
713 float BLF_height(int fontid, const char *str, size_t len)
715 FontBLF *font = blf_get(fontid);
717 if (font && font->glyph_cache) {
718 return blf_font_height(font, str, len);
724 float BLF_height_max(int fontid)
726 FontBLF *font = blf_get(fontid);
728 if (font && font->glyph_cache) {
729 return font->glyph_cache->max_glyph_height;
735 float BLF_width_max(int fontid)
737 FontBLF *font = blf_get(fontid);
739 if (font && font->glyph_cache) {
740 return font->glyph_cache->max_glyph_width;
746 float BLF_descender(int fontid)
748 FontBLF *font = blf_get(fontid);
750 if (font && font->glyph_cache) {
751 return font->glyph_cache->descender;
757 float BLF_ascender(int fontid)
759 FontBLF *font = blf_get(fontid);
761 if (font && font->glyph_cache) {
762 return font->glyph_cache->ascender;
768 float BLF_height_default(const char *str, size_t len)
770 if (!blf_global_font_init())
773 BLF_size(global_font_default, global_font_points, global_font_dpi);
775 return BLF_height(global_font_default, str, len);
778 void BLF_rotation(int fontid, float angle)
780 FontBLF *font = blf_get(fontid);
787 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
789 FontBLF *font = blf_get(fontid);
792 font->clip_rec.xmin = xmin;
793 font->clip_rec.ymin = ymin;
794 font->clip_rec.xmax = xmax;
795 font->clip_rec.ymax = ymax;
799 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
801 FontBLF *font = blf_get(global_font_default);
804 font->clip_rec.xmin = xmin;
805 font->clip_rec.ymin = ymin;
806 font->clip_rec.xmax = xmax;
807 font->clip_rec.ymax = ymax;
811 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
813 FontBLF *font = blf_get(fontid);
816 font->shadow = level;
817 font->shadow_col[0] = r;
818 font->shadow_col[1] = g;
819 font->shadow_col[2] = b;
820 font->shadow_col[3] = a;
824 void BLF_shadow_offset(int fontid, int x, int y)
826 FontBLF *font = blf_get(fontid);
834 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
836 FontBLF *font = blf_get(fontid);
839 font->buf_info.fbuf = fbuf;
840 font->buf_info.cbuf = cbuf;
841 font->buf_info.w = w;
842 font->buf_info.h = h;
843 font->buf_info.ch = nch;
844 font->buf_info.display = display;
848 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
850 FontBLF *font = blf_get(fontid);
853 font->buf_info.col[0] = r;
854 font->buf_info.col[1] = g;
855 font->buf_info.col[2] = b;
856 font->buf_info.col[3] = a;
860 void BLF_draw_buffer(int fontid, const char *str)
862 FontBLF *font = blf_get(fontid);
864 if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
865 blf_font_buffer(font, str);
870 void BLF_state_print(int fontid)
872 FontBLF *font = blf_get(fontid);
874 printf("fontid %d %p\n", fontid, (void *)font);
875 printf(" name: '%s'\n", font->name);
876 printf(" size: %u\n", font->size);
877 printf(" dpi: %u\n", font->dpi);
878 printf(" pos: %.6f %.6f %.6f\n", UNPACK3(font->pos));
879 printf(" aspect: (%d) %.6f %.6f %.6f\n", (font->flags & BLF_ROTATION) != 0, UNPACK3(font->aspect));
880 printf(" angle: (%d) %.6f\n", (font->flags & BLF_ASPECT) != 0, font->angle);
881 printf(" flag: %d\n", font->flags);
884 printf("fontid %d (NULL)\n", fontid);