1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2009 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup blf
22 *
23 * Main BlenFont (BLF) API, public functions for font handling.
24 *
25 * Wraps OpenGL and FreeType.
26 */
27
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <ft2build.h>
34
35 #include FT_FREETYPE_H
36 #include FT_GLYPH_H
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_listBase.h"
41 #include "DNA_userdef_types.h"
42 #include "DNA_vec_types.h"
43
44 #include "BLI_math.h"
45 #include "BLI_threads.h"
46
47 #include "BLF_api.h"
48
49 #include "IMB_colormanagement.h"
50
51 #include "UI_interface.h"
52
53 #include "GPU_immediate.h"
54 #include "GPU_matrix.h"
55 #include "GPU_shader.h"
56
57 #include "blf_internal.h"
58 #include "blf_internal_types.h"
59
60 /* Max number of font in memory.
61 * Take care that now every font have a glyph cache per size/dpi,
62 * so we don't need load the same font with different size, just
63 * load one and call BLF_size.
64 */
65 #define BLF_MAX_FONT 16
66
67 /* call BLF_default_set first! */
68 #define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
69
70 #define BLF_RESULT_CHECK_INIT(r_info) \
71 if (r_info) { \
72 memset(r_info, 0, sizeof(*(r_info))); \
73 } \
74 ((void)0)
75
76 /* Font array. */
77 static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
78
79 /* Default size and dpi, for BLF_draw_default. */
80 static int global_font_default = -1;
81 static int global_font_dpi = 72;
82
83 /* XXX, should these be made into global_font_'s too? */
84 int blf_mono_font = -1;
85 int blf_mono_font_render = -1;
86
blf_get(int fontid)87 static FontBLF *blf_get(int fontid)
88 {
89 if (fontid >= 0 && fontid < BLF_MAX_FONT) {
90 return global_font[fontid];
91 }
92 return NULL;
93 }
94
BLF_init(void)95 int BLF_init(void)
96 {
97 for (int i = 0; i < BLF_MAX_FONT; i++) {
98 global_font[i] = NULL;
99 }
100
101 global_font_dpi = 72;
102
103 return blf_font_init();
104 }
105
BLF_default_dpi(int dpi)106 void BLF_default_dpi(int dpi)
107 {
108 global_font_dpi = dpi;
109 }
110
BLF_exit(void)111 void BLF_exit(void)
112 {
113 for (int i = 0; i < BLF_MAX_FONT; i++) {
114 FontBLF *font = global_font[i];
115 if (font) {
116 blf_font_free(font);
117 global_font[i] = NULL;
118 }
119 }
120
121 blf_font_exit();
122 }
123
BLF_cache_clear(void)124 void BLF_cache_clear(void)
125 {
126 for (int i = 0; i < BLF_MAX_FONT; i++) {
127 FontBLF *font = global_font[i];
128 if (font) {
129 blf_glyph_cache_clear(font);
130 blf_kerning_cache_clear(font);
131 }
132 }
133 }
134
blf_search(const char * name)135 static int blf_search(const char *name)
136 {
137 for (int i = 0; i < BLF_MAX_FONT; i++) {
138 FontBLF *font = global_font[i];
139 if (font && (STREQ(font->name, name))) {
140 return i;
141 }
142 }
143
144 return -1;
145 }
146
blf_search_available(void)147 static int blf_search_available(void)
148 {
149 for (int i = 0; i < BLF_MAX_FONT; i++) {
150 if (!global_font[i]) {
151 return i;
152 }
153 }
154
155 return -1;
156 }
157
BLF_default_set(int fontid)158 void BLF_default_set(int fontid)
159 {
160 FontBLF *font = blf_get(fontid);
161 if (font || fontid == -1) {
162 global_font_default = fontid;
163 }
164 }
165
BLF_default(void)166 int BLF_default(void)
167 {
168 ASSERT_DEFAULT_SET;
169 return global_font_default;
170 }
171
BLF_has_glyph(int fontid,unsigned int unicode)172 bool BLF_has_glyph(int fontid, unsigned int unicode)
173 {
174 FontBLF *font = blf_get(fontid);
175 if (font) {
176 return FT_Get_Char_Index(font->face, unicode) != 0;
177 }
178 return false;
179 }
180
BLF_load(const char * name)181 int BLF_load(const char *name)
182 {
183 /* check if we already load this font. */
184 int i = blf_search(name);
185 if (i >= 0) {
186 FontBLF *font = global_font[i];
187 font->reference_count++;
188 return i;
189 }
190
191 return BLF_load_unique(name);
192 }
193
BLF_load_unique(const char * name)194 int BLF_load_unique(const char *name)
195 {
196 /* Don't search in the cache!! make a new
197 * object font, this is for keep fonts threads safe.
198 */
199 int i = blf_search_available();
200 if (i == -1) {
201 printf("Too many fonts!!!\n");
202 return -1;
203 }
204
205 char *filename = blf_dir_search(name);
206 if (!filename) {
207 printf("Can't find font: %s\n", name);
208 return -1;
209 }
210
211 FontBLF *font = blf_font_new(name, filename);
212 MEM_freeN(filename);
213
214 if (!font) {
215 printf("Can't load font: %s\n", name);
216 return -1;
217 }
218
219 font->reference_count = 1;
220 global_font[i] = font;
221 return i;
222 }
223
BLF_metrics_attach(int fontid,unsigned char * mem,int mem_size)224 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
225 {
226 FontBLF *font = blf_get(fontid);
227
228 if (font) {
229 blf_font_attach_from_mem(font, mem, mem_size);
230 }
231 }
232
BLF_load_mem(const char * name,const unsigned char * mem,int mem_size)233 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
234 {
235 int i = blf_search(name);
236 if (i >= 0) {
237 /*font = global_font[i];*/ /*UNUSED*/
238 return i;
239 }
240 return BLF_load_mem_unique(name, mem, mem_size);
241 }
242
BLF_load_mem_unique(const char * name,const unsigned char * mem,int mem_size)243 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size)
244 {
245 /*
246 * Don't search in the cache, make a new object font!
247 * this is to keep the font thread safe.
248 */
249 int i = blf_search_available();
250 if (i == -1) {
251 printf("Too many fonts!!!\n");
252 return -1;
253 }
254
255 if (!mem_size) {
256 printf("Can't load font: %s from memory!!\n", name);
257 return -1;
258 }
259
260 FontBLF *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 font->reference_count = 1;
267 global_font[i] = font;
268 return i;
269 }
270
BLF_unload(const char * name)271 void BLF_unload(const char *name)
272 {
273 for (int i = 0; i < BLF_MAX_FONT; i++) {
274 FontBLF *font = global_font[i];
275
276 if (font && (STREQ(font->name, name))) {
277 BLI_assert(font->reference_count > 0);
278 font->reference_count--;
279
280 if (font->reference_count == 0) {
281 blf_font_free(font);
282 global_font[i] = NULL;
283 }
284 }
285 }
286 }
287
BLF_unload_id(int fontid)288 void BLF_unload_id(int fontid)
289 {
290 FontBLF *font = blf_get(fontid);
291 if (font) {
292 BLI_assert(font->reference_count > 0);
293 font->reference_count--;
294
295 if (font->reference_count == 0) {
296 blf_font_free(font);
297 global_font[fontid] = NULL;
298 }
299 }
300 }
301
BLF_enable(int fontid,int option)302 void BLF_enable(int fontid, int option)
303 {
304 FontBLF *font = blf_get(fontid);
305
306 if (font) {
307 font->flags |= option;
308 }
309 }
310
BLF_disable(int fontid,int option)311 void BLF_disable(int fontid, int option)
312 {
313 FontBLF *font = blf_get(fontid);
314
315 if (font) {
316 font->flags &= ~option;
317 }
318 }
319
BLF_aspect(int fontid,float x,float y,float z)320 void BLF_aspect(int fontid, float x, float y, float z)
321 {
322 FontBLF *font = blf_get(fontid);
323
324 if (font) {
325 font->aspect[0] = x;
326 font->aspect[1] = y;
327 font->aspect[2] = z;
328 }
329 }
330
BLF_matrix(int fontid,const float m[16])331 void BLF_matrix(int fontid, const float m[16])
332 {
333 FontBLF *font = blf_get(fontid);
334
335 if (font) {
336 memcpy(font->m, m, sizeof(font->m));
337 }
338 }
339
BLF_position(int fontid,float x,float y,float z)340 void BLF_position(int fontid, float x, float y, float z)
341 {
342 FontBLF *font = blf_get(fontid);
343
344 if (font) {
345 float xa, ya, za;
346 float remainder;
347
348 if (font->flags & BLF_ASPECT) {
349 xa = font->aspect[0];
350 ya = font->aspect[1];
351 za = font->aspect[2];
352 }
353 else {
354 xa = 1.0f;
355 ya = 1.0f;
356 za = 1.0f;
357 }
358
359 remainder = x - floorf(x);
360 if (remainder > 0.4f && remainder < 0.6f) {
361 if (remainder < 0.5f) {
362 x -= 0.1f * xa;
363 }
364 else {
365 x += 0.1f * xa;
366 }
367 }
368
369 remainder = y - floorf(y);
370 if (remainder > 0.4f && remainder < 0.6f) {
371 if (remainder < 0.5f) {
372 y -= 0.1f * ya;
373 }
374 else {
375 y += 0.1f * ya;
376 }
377 }
378
379 remainder = z - floorf(z);
380 if (remainder > 0.4f && remainder < 0.6f) {
381 if (remainder < 0.5f) {
382 z -= 0.1f * za;
383 }
384 else {
385 z += 0.1f * za;
386 }
387 }
388
389 font->pos[0] = x;
390 font->pos[1] = y;
391 font->pos[2] = z;
392 }
393 }
394
BLF_size(int fontid,int size,int dpi)395 void BLF_size(int fontid, int size, int dpi)
396 {
397 FontBLF *font = blf_get(fontid);
398
399 if (font) {
400 blf_font_size(font, size, dpi);
401 }
402 }
403
404 #if BLF_BLUR_ENABLE
BLF_blur(int fontid,int size)405 void BLF_blur(int fontid, int size)
406 {
407 FontBLF *font = blf_get(fontid);
408
409 if (font) {
410 font->blur = size;
411 }
412 }
413 #endif
414
BLF_color4ubv(int fontid,const unsigned char rgba[4])415 void BLF_color4ubv(int fontid, const unsigned char rgba[4])
416 {
417 FontBLF *font = blf_get(fontid);
418
419 if (font) {
420 font->color[0] = rgba[0];
421 font->color[1] = rgba[1];
422 font->color[2] = rgba[2];
423 font->color[3] = rgba[3];
424 }
425 }
426
BLF_color3ubv_alpha(int fontid,const unsigned char rgb[3],unsigned char alpha)427 void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha)
428 {
429 FontBLF *font = blf_get(fontid);
430
431 if (font) {
432 font->color[0] = rgb[0];
433 font->color[1] = rgb[1];
434 font->color[2] = rgb[2];
435 font->color[3] = alpha;
436 }
437 }
438
BLF_color3ubv(int fontid,const unsigned char rgb[3])439 void BLF_color3ubv(int fontid, const unsigned char rgb[3])
440 {
441 BLF_color3ubv_alpha(fontid, rgb, 255);
442 }
443
BLF_color4ub(int fontid,unsigned char r,unsigned char g,unsigned char b,unsigned char alpha)444 void BLF_color4ub(
445 int fontid, unsigned char r, unsigned char g, unsigned char b, unsigned char alpha)
446 {
447 FontBLF *font = blf_get(fontid);
448
449 if (font) {
450 font->color[0] = r;
451 font->color[1] = g;
452 font->color[2] = b;
453 font->color[3] = alpha;
454 }
455 }
456
BLF_color3ub(int fontid,unsigned char r,unsigned char g,unsigned char b)457 void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b)
458 {
459 FontBLF *font = blf_get(fontid);
460
461 if (font) {
462 font->color[0] = r;
463 font->color[1] = g;
464 font->color[2] = b;
465 font->color[3] = 255;
466 }
467 }
468
BLF_color4fv(int fontid,const float rgba[4])469 void BLF_color4fv(int fontid, const float rgba[4])
470 {
471 FontBLF *font = blf_get(fontid);
472
473 if (font) {
474 rgba_float_to_uchar(font->color, rgba);
475 }
476 }
477
BLF_color4f(int fontid,float r,float g,float b,float a)478 void BLF_color4f(int fontid, float r, float g, float b, float a)
479 {
480 const float rgba[4] = {r, g, b, a};
481 BLF_color4fv(fontid, rgba);
482 }
483
BLF_color3fv_alpha(int fontid,const float rgb[3],float alpha)484 void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha)
485 {
486 float rgba[4];
487 copy_v3_v3(rgba, rgb);
488 rgba[3] = alpha;
489 BLF_color4fv(fontid, rgba);
490 }
491
BLF_color3f(int fontid,float r,float g,float b)492 void BLF_color3f(int fontid, float r, float g, float b)
493 {
494 const float rgba[4] = {r, g, b, 1.0f};
495 BLF_color4fv(fontid, rgba);
496 }
497
BLF_batch_draw_begin(void)498 void BLF_batch_draw_begin(void)
499 {
500 BLI_assert(g_batch.enabled == false);
501 g_batch.enabled = true;
502 }
503
BLF_batch_draw_flush(void)504 void BLF_batch_draw_flush(void)
505 {
506 if (g_batch.enabled) {
507 blf_batch_draw();
508 }
509 }
510
BLF_batch_draw_end(void)511 void BLF_batch_draw_end(void)
512 {
513 BLI_assert(g_batch.enabled == true);
514 blf_batch_draw(); /* Draw remaining glyphs */
515 g_batch.enabled = false;
516 }
517
BLF_draw_default(float x,float y,float z,const char * str,size_t len)518 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
519 {
520 ASSERT_DEFAULT_SET;
521
522 const uiStyle *style = UI_style_get();
523 BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
524 BLF_position(global_font_default, x, y, z);
525 BLF_draw(global_font_default, str, len);
526 }
527
528 /* same as above but call 'BLF_draw_ascii' */
BLF_draw_default_ascii(float x,float y,float z,const char * str,size_t len)529 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
530 {
531 ASSERT_DEFAULT_SET;
532
533 const uiStyle *style = UI_style_get();
534 BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
535 BLF_position(global_font_default, x, y, z);
536 BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
537 }
538
BLF_set_default(void)539 int BLF_set_default(void)
540 {
541 ASSERT_DEFAULT_SET;
542
543 const uiStyle *style = UI_style_get();
544 BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
545
546 return global_font_default;
547 }
548
blf_draw_gl__start(FontBLF * font)549 static void blf_draw_gl__start(FontBLF *font)
550 {
551 /*
552 * The pixmap alignment hack is handle
553 * in BLF_position (old ui_rasterpos_safe).
554 */
555
556 if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0) {
557 return; /* glyphs will be translated individually and batched. */
558 }
559
560 GPU_matrix_push();
561
562 if (font->flags & BLF_MATRIX) {
563 GPU_matrix_mul(font->m);
564 }
565
566 GPU_matrix_translate_3fv(font->pos);
567
568 if (font->flags & BLF_ASPECT) {
569 GPU_matrix_scale_3fv(font->aspect);
570 }
571
572 if (font->flags & BLF_ROTATION) {
573 GPU_matrix_rotate_2d(RAD2DEG(font->angle));
574 }
575 }
576
blf_draw_gl__end(FontBLF * font)577 static void blf_draw_gl__end(FontBLF *font)
578 {
579 if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0) {
580 GPU_matrix_pop();
581 }
582 }
583
BLF_draw_ex(int fontid,const char * str,size_t len,struct ResultBLF * r_info)584 void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
585 {
586 FontBLF *font = blf_get(fontid);
587
588 BLF_RESULT_CHECK_INIT(r_info);
589
590 if (font) {
591 blf_draw_gl__start(font);
592 if (font->flags & BLF_WORD_WRAP) {
593 blf_font_draw__wrap(font, str, len, r_info);
594 }
595 else {
596 blf_font_draw(font, str, len, r_info);
597 }
598 blf_draw_gl__end(font);
599 }
600 }
BLF_draw(int fontid,const char * str,size_t len)601 void BLF_draw(int fontid, const char *str, size_t len)
602 {
603 if (len == 0 || str[0] == '\0') {
604 return;
605 }
606
607 /* Avoid bgl usage to corrupt BLF drawing. */
608 GPU_bgl_end();
609
610 BLF_draw_ex(fontid, str, len, NULL);
611 }
612
BLF_draw_ascii_ex(int fontid,const char * str,size_t len,struct ResultBLF * r_info)613 void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
614 {
615 FontBLF *font = blf_get(fontid);
616
617 BLF_RESULT_CHECK_INIT(r_info);
618
619 if (font) {
620 blf_draw_gl__start(font);
621 if (font->flags & BLF_WORD_WRAP) {
622 /* use non-ascii draw function for word-wrap */
623 blf_font_draw__wrap(font, str, len, r_info);
624 }
625 else {
626 blf_font_draw_ascii(font, str, len, r_info);
627 }
628 blf_draw_gl__end(font);
629 }
630 }
631
BLF_draw_ascii(int fontid,const char * str,size_t len)632 void BLF_draw_ascii(int fontid, const char *str, size_t len)
633 {
634 if (len == 0 || str[0] == '\0') {
635 return;
636 }
637
638 BLF_draw_ascii_ex(fontid, str, len, NULL);
639 }
640
BLF_draw_mono(int fontid,const char * str,size_t len,int cwidth)641 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
642 {
643 if (len == 0 || str[0] == '\0') {
644 return 0;
645 }
646
647 FontBLF *font = blf_get(fontid);
648 int columns = 0;
649
650 if (font) {
651 blf_draw_gl__start(font);
652 columns = blf_font_draw_mono(font, str, len, cwidth);
653 blf_draw_gl__end(font);
654 }
655
656 return columns;
657 }
658
659 /**
660 * Run \a user_fn for each character, with the bound-box that would be used for drawing.
661 *
662 * \param user_fn: Callback that runs on each glyph, returning false early exits.
663 * \param user_data: User argument passed to \a user_fn.
664 *
665 * \note The font position, clipping, matrix and rotation are not applied.
666 */
BLF_boundbox_foreach_glyph_ex(int fontid,const char * str,size_t len,BLF_GlyphBoundsFn user_fn,void * user_data,struct ResultBLF * r_info)667 void BLF_boundbox_foreach_glyph_ex(int fontid,
668 const char *str,
669 size_t len,
670 BLF_GlyphBoundsFn user_fn,
671 void *user_data,
672 struct ResultBLF *r_info)
673 {
674 FontBLF *font = blf_get(fontid);
675
676 BLF_RESULT_CHECK_INIT(r_info);
677
678 if (font) {
679 if (font->flags & BLF_WORD_WRAP) {
680 /* TODO: word-wrap support. */
681 BLI_assert(0);
682 }
683 else {
684 blf_font_boundbox_foreach_glyph(font, str, len, user_fn, user_data, r_info);
685 }
686 }
687 }
688
BLF_boundbox_foreach_glyph(int fontid,const char * str,size_t len,BLF_GlyphBoundsFn user_fn,void * user_data)689 void BLF_boundbox_foreach_glyph(
690 int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data)
691 {
692 BLF_boundbox_foreach_glyph_ex(fontid, str, len, user_fn, user_data, NULL);
693 }
694
BLF_width_to_strlen(int fontid,const char * str,size_t len,float width,float * r_width)695 size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
696 {
697 FontBLF *font = blf_get(fontid);
698
699 if (font) {
700 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
701 size_t ret;
702 ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
703 if (r_width) {
704 *r_width *= xa;
705 }
706 return ret;
707 }
708
709 if (r_width) {
710 *r_width = 0.0f;
711 }
712 return 0;
713 }
714
BLF_width_to_rstrlen(int fontid,const char * str,size_t len,float width,float * r_width)715 size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
716 {
717 FontBLF *font = blf_get(fontid);
718
719 if (font) {
720 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
721 size_t ret;
722 ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
723 if (r_width) {
724 *r_width *= xa;
725 }
726 return ret;
727 }
728
729 if (r_width) {
730 *r_width = 0.0f;
731 }
732 return 0;
733 }
734
BLF_boundbox_ex(int fontid,const char * str,size_t len,rctf * r_box,struct ResultBLF * r_info)735 void BLF_boundbox_ex(
736 int fontid, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
737 {
738 FontBLF *font = blf_get(fontid);
739
740 BLF_RESULT_CHECK_INIT(r_info);
741
742 if (font) {
743 if (font->flags & BLF_WORD_WRAP) {
744 blf_font_boundbox__wrap(font, str, len, r_box, r_info);
745 }
746 else {
747 blf_font_boundbox(font, str, len, r_box, r_info);
748 }
749 }
750 }
751
BLF_boundbox(int fontid,const char * str,size_t len,rctf * r_box)752 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
753 {
754 BLF_boundbox_ex(fontid, str, len, r_box, NULL);
755 }
756
BLF_width_and_height(int fontid,const char * str,size_t len,float * r_width,float * r_height)757 void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
758 {
759 FontBLF *font = blf_get(fontid);
760
761 if (font) {
762 blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
763 }
764 else {
765 *r_width = *r_height = 0.0f;
766 }
767 }
768
BLF_width_ex(int fontid,const char * str,size_t len,struct ResultBLF * r_info)769 float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
770 {
771 FontBLF *font = blf_get(fontid);
772
773 BLF_RESULT_CHECK_INIT(r_info);
774
775 if (font) {
776 return blf_font_width(font, str, len, r_info);
777 }
778
779 return 0.0f;
780 }
781
BLF_width(int fontid,const char * str,size_t len)782 float BLF_width(int fontid, const char *str, size_t len)
783 {
784 return BLF_width_ex(fontid, str, len, NULL);
785 }
786
BLF_fixed_width(int fontid)787 float BLF_fixed_width(int fontid)
788 {
789 FontBLF *font = blf_get(fontid);
790
791 if (font) {
792 return blf_font_fixed_width(font);
793 }
794
795 return 0.0f;
796 }
797
BLF_height_ex(int fontid,const char * str,size_t len,struct ResultBLF * r_info)798 float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
799 {
800 FontBLF *font = blf_get(fontid);
801
802 BLF_RESULT_CHECK_INIT(r_info);
803
804 if (font) {
805 return blf_font_height(font, str, len, r_info);
806 }
807
808 return 0.0f;
809 }
810
BLF_height(int fontid,const char * str,size_t len)811 float BLF_height(int fontid, const char *str, size_t len)
812 {
813 return BLF_height_ex(fontid, str, len, NULL);
814 }
815
BLF_height_max(int fontid)816 int BLF_height_max(int fontid)
817 {
818 FontBLF *font = blf_get(fontid);
819
820 if (font) {
821 return blf_font_height_max(font);
822 }
823
824 return 0;
825 }
826
BLF_width_max(int fontid)827 float BLF_width_max(int fontid)
828 {
829 FontBLF *font = blf_get(fontid);
830
831 if (font) {
832 return blf_font_width_max(font);
833 }
834
835 return 0.0f;
836 }
837
BLF_descender(int fontid)838 float BLF_descender(int fontid)
839 {
840 FontBLF *font = blf_get(fontid);
841
842 if (font) {
843 return blf_font_descender(font);
844 }
845
846 return 0.0f;
847 }
848
BLF_ascender(int fontid)849 float BLF_ascender(int fontid)
850 {
851 FontBLF *font = blf_get(fontid);
852
853 if (font) {
854 return blf_font_ascender(font);
855 }
856
857 return 0.0f;
858 }
859
BLF_rotation(int fontid,float angle)860 void BLF_rotation(int fontid, float angle)
861 {
862 FontBLF *font = blf_get(fontid);
863
864 if (font) {
865 font->angle = angle;
866 }
867 }
868
BLF_clipping(int fontid,float xmin,float ymin,float xmax,float ymax)869 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
870 {
871 FontBLF *font = blf_get(fontid);
872
873 if (font) {
874 font->clip_rec.xmin = xmin;
875 font->clip_rec.ymin = ymin;
876 font->clip_rec.xmax = xmax;
877 font->clip_rec.ymax = ymax;
878 }
879 }
880
BLF_wordwrap(int fontid,int wrap_width)881 void BLF_wordwrap(int fontid, int wrap_width)
882 {
883 FontBLF *font = blf_get(fontid);
884
885 if (font) {
886 font->wrap_width = wrap_width;
887 }
888 }
889
BLF_shadow(int fontid,int level,const float rgba[4])890 void BLF_shadow(int fontid, int level, const float rgba[4])
891 {
892 FontBLF *font = blf_get(fontid);
893
894 if (font) {
895 font->shadow = level;
896 rgba_float_to_uchar(font->shadow_color, rgba);
897 }
898 }
899
BLF_shadow_offset(int fontid,int x,int y)900 void BLF_shadow_offset(int fontid, int x, int y)
901 {
902 FontBLF *font = blf_get(fontid);
903
904 if (font) {
905 font->shadow_x = x;
906 font->shadow_y = y;
907 }
908 }
909
BLF_buffer(int fontid,float * fbuf,unsigned char * cbuf,int w,int h,int nch,struct ColorManagedDisplay * display)910 void BLF_buffer(int fontid,
911 float *fbuf,
912 unsigned char *cbuf,
913 int w,
914 int h,
915 int nch,
916 struct ColorManagedDisplay *display)
917 {
918 FontBLF *font = blf_get(fontid);
919
920 if (font) {
921 font->buf_info.fbuf = fbuf;
922 font->buf_info.cbuf = cbuf;
923 font->buf_info.dims[0] = w;
924 font->buf_info.dims[1] = h;
925 font->buf_info.ch = nch;
926 font->buf_info.display = display;
927 }
928 }
929
BLF_buffer_col(int fontid,const float rgba[4])930 void BLF_buffer_col(int fontid, const float rgba[4])
931 {
932 FontBLF *font = blf_get(fontid);
933
934 if (font) {
935 copy_v4_v4(font->buf_info.col_init, rgba);
936 }
937 }
938
blf_draw_buffer__start(FontBLF * font)939 void blf_draw_buffer__start(FontBLF *font)
940 {
941 FontBufInfoBLF *buf_info = &font->buf_info;
942
943 rgba_float_to_uchar(buf_info->col_char, buf_info->col_init);
944
945 if (buf_info->display) {
946 copy_v4_v4(buf_info->col_float, buf_info->col_init);
947 IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display);
948 }
949 else {
950 srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init);
951 }
952 }
blf_draw_buffer__end(void)953 void blf_draw_buffer__end(void)
954 {
955 }
956
BLF_draw_buffer_ex(int fontid,const char * str,size_t len,struct ResultBLF * r_info)957 void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
958 {
959 FontBLF *font = blf_get(fontid);
960
961 if (font && (font->buf_info.fbuf || font->buf_info.cbuf)) {
962 blf_draw_buffer__start(font);
963 if (font->flags & BLF_WORD_WRAP) {
964 blf_font_draw_buffer__wrap(font, str, len, r_info);
965 }
966 else {
967 blf_font_draw_buffer(font, str, len, r_info);
968 }
969 blf_draw_buffer__end();
970 }
971 }
BLF_draw_buffer(int fontid,const char * str,size_t len)972 void BLF_draw_buffer(int fontid, const char *str, size_t len)
973 {
974 BLF_draw_buffer_ex(fontid, str, len, NULL);
975 }
976
977 #ifdef DEBUG
BLF_state_print(int fontid)978 void BLF_state_print(int fontid)
979 {
980 FontBLF *font = blf_get(fontid);
981 if (font) {
982 printf("fontid %d %p\n", fontid, (void *)font);
983 printf(" name: '%s'\n", font->name);
984 printf(" size: %u\n", font->size);
985 printf(" dpi: %u\n", font->dpi);
986 printf(" pos: %.6f %.6f %.6f\n", UNPACK3(font->pos));
987 printf(" aspect: (%d) %.6f %.6f %.6f\n",
988 (font->flags & BLF_ROTATION) != 0,
989 UNPACK3(font->aspect));
990 printf(" angle: (%d) %.6f\n", (font->flags & BLF_ASPECT) != 0, font->angle);
991 printf(" flag: %d\n", font->flags);
992 }
993 else {
994 printf("fontid %d (NULL)\n", fontid);
995 }
996 fflush(stdout);
997 }
998 #endif
999