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