doxygen: add newline after \file
[blender.git] / source / blender / blenfont / intern / blf.c
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 <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.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_vec_types.h"
42
43 #include "BLI_math.h"
44 #include "BLI_threads.h"
45
46 #include "BLF_api.h"
47
48 #include "IMB_colormanagement.h"
49
50 #ifndef BLF_STANDALONE
51 #include "GPU_shader.h"
52 #include "GPU_matrix.h"
53 #include "GPU_immediate.h"
54 #endif
55
56 #include "blf_internal_types.h"
57 #include "blf_internal.h"
58
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.
63  */
64 #define BLF_MAX_FONT 16
65
66 /* call BLF_default_set first! */
67 #define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
68
69 #define BLF_RESULT_CHECK_INIT(r_info) \
70 if (r_info) { \
71         memset(r_info, 0, sizeof(*(r_info))); \
72 } ((void)0)
73
74 /* Font array. */
75 static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
76
77 /* Default size and dpi, for BLF_draw_default. */
78 static int global_font_default = -1;
79 static int global_font_points = 11;
80 static int global_font_dpi = 72;
81
82 /* XXX, should these be made into global_font_'s too? */
83 int blf_mono_font = -1;
84 int blf_mono_font_render = -1;
85
86 static FontBLF *blf_get(int fontid)
87 {
88         if (fontid >= 0 && fontid < BLF_MAX_FONT)
89                 return global_font[fontid];
90         return NULL;
91 }
92
93 int BLF_init(void)
94 {
95         int i;
96
97         for (i = 0; i < BLF_MAX_FONT; i++)
98                 global_font[i] = NULL;
99
100         global_font_points = 11;
101         global_font_dpi = 72;
102
103         return blf_font_init();
104 }
105
106 void BLF_default_dpi(int dpi)
107 {
108         global_font_dpi = dpi;
109 }
110
111 void BLF_exit(void)
112 {
113         FontBLF *font;
114         int i;
115
116         for (i = 0; i < BLF_MAX_FONT; i++) {
117                 font = global_font[i];
118                 if (font) {
119                         blf_font_free(font);
120                         global_font[i] = NULL;
121                 }
122         }
123
124         blf_font_exit();
125 }
126
127 void BLF_batch_reset(void)
128 {
129         blf_batch_draw_vao_clear();
130 }
131
132 void BLF_cache_clear(void)
133 {
134         FontBLF *font;
135         int i;
136
137         for (i = 0; i < BLF_MAX_FONT; i++) {
138                 font = global_font[i];
139                 if (font) {
140                         blf_glyph_cache_clear(font);
141                         blf_kerning_cache_clear(font);
142                 }
143         }
144 }
145
146 static int blf_search(const char *name)
147 {
148         FontBLF *font;
149         int i;
150
151         for (i = 0; i < BLF_MAX_FONT; i++) {
152                 font = global_font[i];
153                 if (font && (STREQ(font->name, name)))
154                         return i;
155         }
156
157         return -1;
158 }
159
160 static int blf_search_available(void)
161 {
162         int i;
163
164         for (i = 0; i < BLF_MAX_FONT; i++)
165                 if (!global_font[i])
166                         return i;
167
168         return -1;
169 }
170
171 void BLF_default_set(int fontid)
172 {
173         FontBLF *font = blf_get(fontid);
174         if (font || fontid == -1) {
175                 global_font_default = fontid;
176         }
177 }
178
179 int BLF_default(void)
180 {
181         ASSERT_DEFAULT_SET;
182         return global_font_default;
183 }
184
185 int BLF_load(const char *name)
186 {
187         FontBLF *font;
188         int i;
189
190         /* check if we already load this font. */
191         i = blf_search(name);
192         if (i >= 0) {
193                 font = global_font[i];
194                 font->reference_count++;
195                 return i;
196         }
197
198         return BLF_load_unique(name);
199 }
200
201 int BLF_load_unique(const char *name)
202 {
203         FontBLF *font;
204         char *filename;
205         int i;
206
207         /* Don't search in the cache!! make a new
208          * object font, this is for keep fonts threads safe.
209          */
210         i = blf_search_available();
211         if (i == -1) {
212                 printf("Too many fonts!!!\n");
213                 return -1;
214         }
215
216         filename = blf_dir_search(name);
217         if (!filename) {
218                 printf("Can't find font: %s\n", name);
219                 return -1;
220         }
221
222         font = blf_font_new(name, filename);
223         MEM_freeN(filename);
224
225         if (!font) {
226                 printf("Can't load font: %s\n", name);
227                 return -1;
228         }
229
230         font->reference_count = 1;
231         global_font[i] = font;
232         return i;
233 }
234
235 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
236 {
237         FontBLF *font = blf_get(fontid);
238
239         if (font) {
240                 blf_font_attach_from_mem(font, mem, mem_size);
241         }
242 }
243
244 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
245 {
246         int i;
247
248         i = blf_search(name);
249         if (i >= 0) {
250                 /*font = global_font[i];*/ /*UNUSED*/
251                 return i;
252         }
253         return BLF_load_mem_unique(name, mem, mem_size);
254 }
255
256 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size)
257 {
258         FontBLF *font;
259         int i;
260
261         /*
262          * Don't search in the cache, make a new object font!
263          * this is to keep the font thread safe.
264          */
265         i = blf_search_available();
266         if (i == -1) {
267                 printf("Too many fonts!!!\n");
268                 return -1;
269         }
270
271         if (!mem_size) {
272                 printf("Can't load font: %s from memory!!\n", name);
273                 return -1;
274         }
275
276         font = blf_font_new_from_mem(name, mem, mem_size);
277         if (!font) {
278                 printf("Can't load font: %s from memory!!\n", name);
279                 return -1;
280         }
281
282         font->reference_count = 1;
283         global_font[i] = font;
284         return i;
285 }
286
287 void BLF_unload(const char *name)
288 {
289         FontBLF *font;
290         int i;
291
292         for (i = 0; i < BLF_MAX_FONT; i++) {
293                 font = global_font[i];
294
295                 if (font && (STREQ(font->name, name))) {
296                         BLI_assert(font->reference_count > 0);
297                         font->reference_count--;
298
299                         if (font->reference_count == 0) {
300                                 blf_font_free(font);
301                                 global_font[i] = NULL;
302                         }
303                 }
304         }
305 }
306
307 void BLF_unload_id(int fontid)
308 {
309         FontBLF *font = blf_get(fontid);
310         if (font) {
311                 BLI_assert(font->reference_count > 0);
312                 font->reference_count--;
313
314                 if (font->reference_count == 0) {
315                         blf_font_free(font);
316                         global_font[fontid] = NULL;
317                 }
318         }
319 }
320
321 void BLF_enable(int fontid, int option)
322 {
323         FontBLF *font = blf_get(fontid);
324
325         if (font) {
326                 font->flags |= option;
327         }
328 }
329
330 void BLF_disable(int fontid, int option)
331 {
332         FontBLF *font = blf_get(fontid);
333
334         if (font) {
335                 font->flags &= ~option;
336         }
337 }
338
339 void BLF_aspect(int fontid, float x, float y, float z)
340 {
341         FontBLF *font = blf_get(fontid);
342
343         if (font) {
344                 font->aspect[0] = x;
345                 font->aspect[1] = y;
346                 font->aspect[2] = z;
347         }
348 }
349
350 void BLF_matrix(int fontid, const float m[16])
351 {
352         FontBLF *font = blf_get(fontid);
353
354         if (font) {
355                 memcpy(font->m, m, sizeof(font->m));
356         }
357 }
358
359 void BLF_position(int fontid, float x, float y, float z)
360 {
361         FontBLF *font = blf_get(fontid);
362
363         if (font) {
364                 float xa, ya, za;
365                 float remainder;
366
367                 if (font->flags & BLF_ASPECT) {
368                         xa = font->aspect[0];
369                         ya = font->aspect[1];
370                         za = font->aspect[2];
371                 }
372                 else {
373                         xa = 1.0f;
374                         ya = 1.0f;
375                         za = 1.0f;
376                 }
377
378                 remainder = x - floorf(x);
379                 if (remainder > 0.4f && remainder < 0.6f) {
380                         if (remainder < 0.5f)
381                                 x -= 0.1f * xa;
382                         else
383                                 x += 0.1f * xa;
384                 }
385
386                 remainder = y - floorf(y);
387                 if (remainder > 0.4f && remainder < 0.6f) {
388                         if (remainder < 0.5f)
389                                 y -= 0.1f * ya;
390                         else
391                                 y += 0.1f * ya;
392                 }
393
394                 remainder = z - floorf(z);
395                 if (remainder > 0.4f && remainder < 0.6f) {
396                         if (remainder < 0.5f)
397                                 z -= 0.1f * za;
398                         else
399                                 z += 0.1f * za;
400                 }
401
402                 font->pos[0] = x;
403                 font->pos[1] = y;
404                 font->pos[2] = z;
405         }
406 }
407
408 void BLF_size(int fontid, int size, int dpi)
409 {
410         FontBLF *font = blf_get(fontid);
411
412         if (font) {
413                 blf_font_size(font, size, dpi);
414         }
415 }
416
417 #if BLF_BLUR_ENABLE
418 void BLF_blur(int fontid, int size)
419 {
420         FontBLF *font = blf_get(fontid);
421
422         if (font) {
423                 font->blur = size;
424         }
425 }
426 #endif
427
428 void BLF_color4ubv(int fontid, const unsigned char rgba[4])
429 {
430         FontBLF *font = blf_get(fontid);
431
432         if (font) {
433                 font->color[0] = rgba[0];
434                 font->color[1] = rgba[1];
435                 font->color[2] = rgba[2];
436                 font->color[3] = rgba[3];
437         }
438 }
439
440 void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha)
441 {
442         FontBLF *font = blf_get(fontid);
443
444         if (font) {
445                 font->color[0] = rgb[0];
446                 font->color[1] = rgb[1];
447                 font->color[2] = rgb[2];
448                 font->color[3] = alpha;
449         }
450 }
451
452 void BLF_color3ubv(int fontid, const unsigned char rgb[3])
453 {
454         BLF_color3ubv_alpha(fontid, rgb, 255);
455 }
456
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
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
478 void BLF_color4f(int fontid, float r, float g, float b, float a)
479 {
480         float rgba[4] = { r, g, b, a };
481         BLF_color4fv(fontid, rgba);
482 }
483
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
492 void BLF_color3f(int fontid, float r, float g, float b)
493 {
494         float rgba[4] = { r, g, b, 1.0f };
495         BLF_color4fv(fontid, rgba);
496 }
497
498 void BLF_batch_draw_begin(void)
499 {
500         BLI_assert(g_batch.enabled == false);
501         g_batch.enabled = true;
502 }
503
504 void BLF_batch_draw_flush(void)
505 {
506         if (g_batch.enabled) {
507                 blf_batch_draw();
508         }
509 }
510
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
518 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
519 {
520         ASSERT_DEFAULT_SET;
521
522         BLF_size(global_font_default, global_font_points, global_font_dpi);
523         BLF_position(global_font_default, x, y, z);
524         BLF_draw(global_font_default, str, len);
525 }
526
527 /* same as above but call 'BLF_draw_ascii' */
528 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
529 {
530         ASSERT_DEFAULT_SET;
531
532         BLF_size(global_font_default, global_font_points, global_font_dpi);
533         BLF_position(global_font_default, x, y, z);
534         BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
535 }
536
537 int BLF_set_default(void)
538 {
539         ASSERT_DEFAULT_SET;
540
541         BLF_size(global_font_default, global_font_points, global_font_dpi);
542
543         return global_font_default;
544 }
545
546 static void blf_draw_gl__start(FontBLF *font)
547 {
548         /*
549          * The pixmap alignment hack is handle
550          * in BLF_position (old ui_rasterpos_safe).
551          */
552
553         /* always bind the texture for the first glyph */
554         font->tex_bind_state = 0;
555
556         if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
557                 return; /* glyphs will be translated individually and batched. */
558
559         GPU_matrix_push();
560
561         if (font->flags & BLF_MATRIX)
562                 GPU_matrix_mul(font->m);
563
564         GPU_matrix_translate_3fv(font->pos);
565
566         if (font->flags & BLF_ASPECT)
567                 GPU_matrix_scale_3fv(font->aspect);
568
569         if (font->flags & BLF_ROTATION)
570                 GPU_matrix_rotate_2d(RAD2DEG(font->angle));
571 }
572
573 static void blf_draw_gl__end(FontBLF *font)
574 {
575         if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
576                 GPU_matrix_pop();
577 }
578
579 void BLF_draw_ex(
580         int fontid, const char *str, size_t len,
581         struct ResultBLF *r_info)
582 {
583         FontBLF *font = blf_get(fontid);
584
585         BLF_RESULT_CHECK_INIT(r_info);
586
587         if (font && font->glyph_cache) {
588                 blf_draw_gl__start(font);
589                 if (font->flags & BLF_WORD_WRAP) {
590                         blf_font_draw__wrap(font, str, len, r_info);
591                 }
592                 else {
593                         blf_font_draw(font, str, len, r_info);
594                 }
595                 blf_draw_gl__end(font);
596         }
597 }
598 void BLF_draw(int fontid, const char *str, size_t len)
599 {
600         if (len == 0 || str[0] == '\0') {
601                 return;
602         }
603
604         BLF_draw_ex(fontid, str, len, NULL);
605 }
606
607 void BLF_draw_ascii_ex(
608         int fontid, const char *str, size_t len,
609         struct ResultBLF *r_info)
610 {
611         FontBLF *font = blf_get(fontid);
612
613         BLF_RESULT_CHECK_INIT(r_info);
614
615         if (font && font->glyph_cache) {
616                 blf_draw_gl__start(font);
617                 if (font->flags & BLF_WORD_WRAP) {
618                         /* use non-ascii draw function for word-wrap */
619                         blf_font_draw__wrap(font, str, len, r_info);
620                 }
621                 else {
622                         blf_font_draw_ascii(font, str, len, r_info);
623                 }
624                 blf_draw_gl__end(font);
625         }
626 }
627 void BLF_draw_ascii(int fontid, const char *str, size_t len)
628 {
629         if (len == 0 || str[0] == '\0') {
630                 return;
631         }
632
633         BLF_draw_ascii_ex(fontid, str, len, NULL);
634 }
635
636 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
637 {
638         if (len == 0 || str[0] == '\0') {
639                 return 0;
640         }
641
642         FontBLF *font = blf_get(fontid);
643         int columns = 0;
644
645         if (font && font->glyph_cache) {
646                 blf_draw_gl__start(font);
647                 columns = blf_font_draw_mono(font, str, len, cwidth);
648                 blf_draw_gl__end(font);
649         }
650
651         return columns;
652 }
653
654 size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
655 {
656         FontBLF *font = blf_get(fontid);
657
658         if (font) {
659                 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
660                 size_t ret;
661                 ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
662                 if (r_width) {
663                         *r_width *= xa;
664                 }
665                 return ret;
666         }
667
668         if (r_width) {
669                 *r_width = 0.0f;
670         }
671         return 0;
672 }
673
674 size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
675 {
676         FontBLF *font = blf_get(fontid);
677
678         if (font) {
679                 const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
680                 size_t ret;
681                 ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
682                 if (r_width) {
683                         *r_width *= xa;
684                 }
685                 return ret;
686         }
687
688         if (r_width) {
689                 *r_width = 0.0f;
690         }
691         return 0;
692 }
693
694 void BLF_boundbox_ex(
695         int fontid, const char *str, size_t len, rctf *r_box,
696         struct ResultBLF *r_info)
697 {
698         FontBLF *font = blf_get(fontid);
699
700         BLF_RESULT_CHECK_INIT(r_info);
701
702         if (font) {
703                 if (font->flags & BLF_WORD_WRAP) {
704                         blf_font_boundbox__wrap(font, str, len, r_box, r_info);
705                 }
706                 else {
707                         blf_font_boundbox(font, str, len, r_box, r_info);
708                 }
709         }
710 }
711 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
712 {
713         BLF_boundbox_ex(fontid, str, len, r_box, NULL);
714 }
715
716 void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
717 {
718         FontBLF *font = blf_get(fontid);
719
720         if (font && font->glyph_cache) {
721                 blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
722         }
723         else {
724                 *r_width = *r_height = 0.0f;
725         }
726 }
727
728 float BLF_width_ex(
729         int fontid, const char *str, size_t len,
730         struct ResultBLF *r_info)
731 {
732         FontBLF *font = blf_get(fontid);
733
734         BLF_RESULT_CHECK_INIT(r_info);
735
736         if (font && font->glyph_cache) {
737                 return blf_font_width(font, str, len, r_info);
738         }
739
740         return 0.0f;
741 }
742 float BLF_width(int fontid, const char *str, size_t len)
743 {
744         return BLF_width_ex(fontid, str, len, NULL);
745 }
746
747 float BLF_fixed_width(int fontid)
748 {
749         FontBLF *font = blf_get(fontid);
750
751         if (font && font->glyph_cache) {
752                 return blf_font_fixed_width(font);
753         }
754
755         return 0.0f;
756 }
757
758 float BLF_height_ex(
759         int fontid, const char *str, size_t len,
760         struct ResultBLF *r_info)
761 {
762         FontBLF *font = blf_get(fontid);
763
764         BLF_RESULT_CHECK_INIT(r_info);
765
766         if (font && font->glyph_cache) {
767                 return blf_font_height(font, str, len, r_info);
768         }
769
770         return 0.0f;
771 }
772 float BLF_height(int fontid, const char *str, size_t len)
773 {
774         return BLF_height_ex(fontid, str, len, NULL);
775 }
776
777 int BLF_height_max(int fontid)
778 {
779         FontBLF *font = blf_get(fontid);
780
781         if (font && font->glyph_cache) {
782                 return font->glyph_cache->glyph_height_max;
783         }
784
785         return 0;
786 }
787
788 float BLF_width_max(int fontid)
789 {
790         FontBLF *font = blf_get(fontid);
791
792         if (font && font->glyph_cache) {
793                 return font->glyph_cache->glyph_width_max;
794         }
795
796         return 0.0f;
797 }
798
799 float BLF_descender(int fontid)
800 {
801         FontBLF *font = blf_get(fontid);
802
803         if (font && font->glyph_cache) {
804                 return font->glyph_cache->descender;
805         }
806
807         return 0.0f;
808 }
809
810 float BLF_ascender(int fontid)
811 {
812         FontBLF *font = blf_get(fontid);
813
814         if (font && font->glyph_cache) {
815                 return font->glyph_cache->ascender;
816         }
817
818         return 0.0f;
819 }
820
821 void BLF_rotation(int fontid, float angle)
822 {
823         FontBLF *font = blf_get(fontid);
824
825         if (font) {
826                 font->angle = angle;
827         }
828 }
829
830 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
831 {
832         FontBLF *font = blf_get(fontid);
833
834         if (font) {
835                 font->clip_rec.xmin = xmin;
836                 font->clip_rec.ymin = ymin;
837                 font->clip_rec.xmax = xmax;
838                 font->clip_rec.ymax = ymax;
839         }
840 }
841
842 void BLF_wordwrap(int fontid, int wrap_width)
843 {
844         FontBLF *font = blf_get(fontid);
845
846         if (font) {
847                 font->wrap_width = wrap_width;
848         }
849 }
850
851 void BLF_shadow(int fontid, int level, const float rgba[4])
852 {
853         FontBLF *font = blf_get(fontid);
854
855         if (font) {
856                 font->shadow = level;
857                 rgba_float_to_uchar(font->shadow_color, rgba);
858         }
859 }
860
861 void BLF_shadow_offset(int fontid, int x, int y)
862 {
863         FontBLF *font = blf_get(fontid);
864
865         if (font) {
866                 font->shadow_x = x;
867                 font->shadow_y = y;
868         }
869 }
870
871 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
872 {
873         FontBLF *font = blf_get(fontid);
874
875         if (font) {
876                 font->buf_info.fbuf = fbuf;
877                 font->buf_info.cbuf = cbuf;
878                 font->buf_info.w = w;
879                 font->buf_info.h = h;
880                 font->buf_info.ch = nch;
881                 font->buf_info.display = display;
882         }
883 }
884
885 void BLF_buffer_col(int fontid, const float rgba[4])
886 {
887         FontBLF *font = blf_get(fontid);
888
889         if (font) {
890                 copy_v4_v4(font->buf_info.col_init, rgba);
891         }
892 }
893
894
895 void blf_draw_buffer__start(FontBLF *font)
896 {
897         FontBufInfoBLF *buf_info = &font->buf_info;
898
899         buf_info->col_char[0] = buf_info->col_init[0] * 255;
900         buf_info->col_char[1] = buf_info->col_init[1] * 255;
901         buf_info->col_char[2] = buf_info->col_init[2] * 255;
902         buf_info->col_char[3] = buf_info->col_init[3] * 255;
903
904         if (buf_info->display) {
905                 copy_v4_v4(buf_info->col_float, buf_info->col_init);
906                 IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display);
907         }
908         else {
909                 srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init);
910         }
911 }
912 void blf_draw_buffer__end(void) {}
913
914 void BLF_draw_buffer_ex(
915         int fontid, const char *str, size_t len,
916         struct ResultBLF *r_info)
917 {
918         FontBLF *font = blf_get(fontid);
919
920         if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
921                 blf_draw_buffer__start(font);
922                 if (font->flags & BLF_WORD_WRAP) {
923                         blf_font_draw_buffer__wrap(font, str, len, r_info);
924                 }
925                 else {
926                         blf_font_draw_buffer(font, str, len, r_info);
927                 }
928                 blf_draw_buffer__end();
929         }
930 }
931 void BLF_draw_buffer(
932         int fontid, const char *str, size_t len)
933 {
934         BLF_draw_buffer_ex(fontid, str, len, NULL);
935 }
936
937 #ifdef DEBUG
938 void BLF_state_print(int fontid)
939 {
940         FontBLF *font = blf_get(fontid);
941         if (font) {
942                 printf("fontid %d %p\n", fontid, (void *)font);
943                 printf("  name:    '%s'\n", font->name);
944                 printf("  size:     %u\n", font->size);
945                 printf("  dpi:      %u\n", font->dpi);
946                 printf("  pos:      %.6f %.6f %.6f\n", UNPACK3(font->pos));
947                 printf("  aspect:   (%d) %.6f %.6f %.6f\n", (font->flags & BLF_ROTATION) != 0, UNPACK3(font->aspect));
948                 printf("  angle:    (%d) %.6f\n", (font->flags & BLF_ASPECT) != 0, font->angle);
949                 printf("  flag:     %d\n", font->flags);
950         }
951         else {
952                 printf("fontid %d (NULL)\n", fontid);
953         }
954         fflush(stdout);
955 }
956 #endif