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