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