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