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