BLF: Fix problem with bound texture.
[blender.git] / source / blender / blenfont / intern / blf_font.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_font.c
28  *  \ingroup blf
29  *
30  * Deals with drawing text to OpenGL or bitmap buffers.
31  *
32  * Also low level functions for managing \a FontBLF.
33  */
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <math.h>
40
41 #include <ft2build.h>
42
43 #include FT_FREETYPE_H
44 #include FT_GLYPH_H
45
46 #include "MEM_guardedalloc.h"
47
48 #include "DNA_vec_types.h"
49
50 #include "BLI_listbase.h"
51 #include "BLI_math.h"
52 #include "BLI_rect.h"
53 #include "BLI_string.h"
54 #include "BLI_string_utf8.h"
55 #include "BLI_threads.h"
56 #include "BLI_alloca.h"
57
58 #include "BIF_gl.h"
59 #include "BLF_api.h"
60
61 #include "UI_interface.h"
62
63 #include "GPU_immediate.h"
64 #include "GPU_matrix.h"
65 #include "GPU_batch.h"
66
67 #include "blf_internal_types.h"
68 #include "blf_internal.h"
69
70 #include "BLI_strict_flags.h"
71
72 #ifdef WIN32
73 #  define FT_New_Face FT_New_Face__win32_compat
74 #endif
75
76 /* Batching buffer for drawing. */
77 BatchBLF g_batch;
78
79 /* freetype2 handle ONLY for this file!. */
80 static FT_Library ft_lib;
81 static SpinLock ft_lib_mutex;
82
83 /* -------------------------------------------------------------------- */
84 /** \name Glyph Batching
85  * \{ */
86 /**
87  * Drawcalls are precious! make them count!
88  * Since most of the Text elems are not covered by other UI elements, we can
89  * group some strings together and render them in one drawcall. This behaviour
90  * is on demand only, between BLF_batch_start() and BLF_batch_end().
91  **/
92 static void blf_batch_draw_init(void)
93 {
94         Gwn_VertFormat format = {0};
95         g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
96         g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
97         g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
98
99         g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
100         GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
101
102         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
103         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
104         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
105         g_batch.glyph_len = 0;
106
107         g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
108 }
109
110 static void blf_batch_draw_exit(void)
111 {
112         GWN_BATCH_DISCARD_SAFE(g_batch.batch);
113 }
114
115 void blf_batch_draw_vao_clear(void)
116 {
117         if (g_batch.batch) {
118                 gwn_batch_vao_cache_clear(g_batch.batch);
119         }
120 }
121
122 void blf_batch_draw_begin(FontBLF *font)
123 {
124         if (g_batch.batch == NULL) {
125                 blf_batch_draw_init();
126         }
127
128         const bool font_changed = (g_batch.font != font);
129         const bool simple_shader = ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0);
130         const bool shader_changed = (simple_shader != g_batch.simple_shader);
131
132         g_batch.active = g_batch.enabled && simple_shader;
133
134         if (simple_shader) {
135                 /* Offset is applied to each glyph. */
136                 copy_v2_v2(g_batch.ofs, font->pos);
137         }
138         else {
139                 /* Offset is baked in modelview mat. */
140                 zero_v2(g_batch.ofs);
141         }
142
143         if (g_batch.active) {
144                 float gpumat[4][4];
145                 gpuGetModelViewMatrix(gpumat);
146
147                 bool mat_changed = (memcmp(gpumat, g_batch.mat, sizeof(g_batch.mat)) != 0);
148
149                 if (mat_changed) {
150                         /* Modelviewmat is no longer the same.
151                          * Flush cache but with the previous mat. */
152                         gpuPushMatrix();
153                         gpuLoadMatrix(g_batch.mat);
154                 }
155
156                 /* flush cache if config is not the same. */
157                 if (mat_changed || font_changed || shader_changed) {
158                         blf_batch_draw();
159                         g_batch.simple_shader = simple_shader;
160                         g_batch.font = font;
161                 }
162                 else {
163                         /* Nothing changed continue batching. */
164                         return;
165                 }
166
167                 if (mat_changed) {
168                         gpuPopMatrix();
169                         /* Save for next memcmp. */
170                         memcpy(g_batch.mat, gpumat, sizeof(g_batch.mat));
171                 }
172         }
173         else {
174                 /* flush cache */
175                 blf_batch_draw();
176                 g_batch.font = font;
177                 g_batch.simple_shader = simple_shader;
178         }
179 }
180
181 void blf_batch_draw(void)
182 {
183         if (g_batch.glyph_len == 0)
184                 return;
185
186         glEnable(GL_BLEND);
187         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
188
189         /* We need to flush widget base first to ensure correct ordering. */
190         UI_widgetbase_draw_cache_flush();
191
192         BLI_assert(g_batch.tex_bind_state != 0); /* must still be valid */
193         glActiveTexture(GL_TEXTURE0);
194         glBindTexture(GL_TEXTURE_2D, g_batch.tex_bind_state);
195
196         GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len);
197         GWN_vertbuf_use(g_batch.verts); /* send data */
198
199         GPUBuiltinShader shader = (g_batch.simple_shader) ? GPU_SHADER_TEXT_SIMPLE : GPU_SHADER_TEXT;
200         GWN_batch_program_set_builtin(g_batch.batch, shader);
201         GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
202         GWN_batch_draw(g_batch.batch);
203
204         glDisable(GL_BLEND);
205
206         /* restart to 1st vertex data pointers */
207         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
208         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
209         GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
210         g_batch.glyph_len = 0;
211 }
212
213 static void blf_batch_draw_end(void)
214 {
215         if (!g_batch.active) {
216                 blf_batch_draw();
217         }
218 }
219
220 /** \} */
221
222 /* -------------------------------------------------------------------- */
223
224 int blf_font_init(void)
225 {
226         memset(&g_batch, 0, sizeof(g_batch));
227         BLI_spin_init(&ft_lib_mutex);
228         return FT_Init_FreeType(&ft_lib);
229 }
230
231 void blf_font_exit(void)
232 {
233         FT_Done_FreeType(ft_lib);
234         BLI_spin_end(&ft_lib_mutex);
235         blf_batch_draw_exit();
236 }
237
238 void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
239 {
240         GlyphCacheBLF *gc;
241         FT_Error err;
242
243         gc = blf_glyph_cache_find(font, size, dpi);
244         if (gc) {
245                 font->glyph_cache = gc;
246                 /* Optimization: do not call FT_Set_Char_Size if size did not change. */
247                 if (font->size == size && font->dpi == dpi)
248                         return;
249         }
250
251         err = FT_Set_Char_Size(font->face, 0, (FT_F26Dot6)(size * 64), dpi, dpi);
252         if (err) {
253                 /* FIXME: here we can go through the fixed size and choice a close one */
254                 printf("The current font don't support the size, %u and dpi, %u\n", size, dpi);
255                 return;
256         }
257
258         font->size = size;
259         font->dpi = dpi;
260
261         if (!gc) {
262                 gc = blf_glyph_cache_new(font);
263                 if (gc)
264                         font->glyph_cache = gc;
265                 else
266                         font->glyph_cache = NULL;
267         }
268 }
269
270 static void blf_font_ensure_ascii_table(FontBLF *font)
271 {
272         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
273
274         /* build ascii on demand */
275         if (glyph_ascii_table['0'] == NULL) {
276                 GlyphBLF *g;
277                 unsigned int i;
278                 for (i = 0; i < 256; i++) {
279                         g = blf_glyph_search(font->glyph_cache, i);
280                         if (!g) {
281                                 FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
282                                 g = blf_glyph_add(font, glyph_index, i);
283                         }
284                         glyph_ascii_table[i] = g;
285                 }
286         }
287 }
288
289 static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode)
290 {
291         KerningCacheBLF *kc = font->kerning_cache;
292
293         font->kerning_mode = kern_mode;
294
295         if (!kc || kc->mode != kern_mode) {
296                 font->kerning_cache = kc = blf_kerning_cache_find(font);
297                 if (!kc) {
298                         font->kerning_cache = kc = blf_kerning_cache_new(font);
299                 }
300         }
301 }
302
303 /* Fast path for runs of ASCII characters. Given that common UTF-8
304  * input will consist of an overwhelming majority of ASCII
305  * characters.
306  */
307
308 /* Note,
309  * blf_font_ensure_ascii_table(font); must be called before this macro */
310
311 #define BLF_UTF8_NEXT_FAST(_font, _g, _str, _i, _c, _glyph_ascii_table)          \
312         if (((_c) = (_str)[_i]) < 0x80) {                                            \
313                 _g = (_glyph_ascii_table)[_c];                                           \
314                 _i++;                                                                    \
315         }                                                                            \
316         else if ((_c = BLI_str_utf8_as_unicode_step(_str, &(_i))) != BLI_UTF8_ERR) { \
317                 if ((_g = blf_glyph_search((_font)->glyph_cache, _c)) == NULL) {         \
318                         _g = blf_glyph_add(_font,                                            \
319                                           FT_Get_Char_Index((_font)->face, _c), _c);         \
320                 }                                                                        \
321         } (void)0
322
323
324 #define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode)                        \
325         const bool _has_kerning = FT_HAS_KERNING((_font)->face) != 0;                \
326         const FT_UInt _kern_mode = (_has_kerning == 0) ? 0 :                         \
327                                  (((_font)->flags & BLF_KERNING_DEFAULT) ?           \
328                                   ft_kerning_default : (FT_UInt)FT_KERNING_UNFITTED) \
329
330 /* Note,
331  * blf_font_ensure_ascii_kerning(font, kern_mode); must be called before this macro */
332
333 #define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \
334 {                                                                                \
335         if (_g_prev) {                                                               \
336                 FT_Vector _delta;                                                        \
337                 if (_c_prev < 0x80 && _c < 0x80) {                                       \
338                         _pen_x += (_font)->kerning_cache->table[_c][_c_prev];                 \
339                 }                                                                        \
340                 else if (FT_Get_Kerning((_font)->face,                                   \
341                                         (_g_prev)->idx,                                  \
342                                         (_g)->idx,                                       \
343                                         _kern_mode,                                      \
344                                         &(_delta)) == 0)                                 \
345                 {                                                                        \
346                         _pen_x += (int)_delta.x >> 6;                                        \
347                 }                                                                        \
348         }                                                                            \
349 } (void)0
350
351 #define BLF_KERNING_STEP(_font, _kern_mode, _g_prev, _g, _delta, _pen_x)         \
352 {                                                                                \
353         if (_g_prev) {                                                               \
354                 _delta.x = _delta.y = 0;                                                 \
355                 if (FT_Get_Kerning((_font)->face,                                        \
356                                    (_g_prev)->idx,                                       \
357                                    (_g)->idx,                                            \
358                                    _kern_mode,                                           \
359                                    &(_delta)) == 0)                                      \
360                 {                                                                        \
361                         _pen_x += (int)_delta.x >> 6;                                        \
362                 }                                                                        \
363         }                                                                            \
364 } (void)0
365
366 static void blf_font_draw_ex(
367         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
368         int pen_y)
369 {
370         unsigned int c, c_prev = BLI_UTF8_ERR;
371         GlyphBLF *g, *g_prev = NULL;
372         int pen_x = 0;
373         size_t i = 0;
374         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
375
376         if (len == 0) {
377                 /* early output, don't do any IMM OpenGL. */
378                 return;
379         }
380
381         BLF_KERNING_VARS(font, has_kerning, kern_mode);
382
383         blf_font_ensure_ascii_table(font);
384         blf_font_ensure_ascii_kerning(font, kern_mode);
385
386         blf_batch_draw_begin(font);
387
388         while ((i < len) && str[i]) {
389                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
390
391                 if (UNLIKELY(c == BLI_UTF8_ERR))
392                         break;
393                 if (UNLIKELY(g == NULL))
394                         continue;
395                 if (has_kerning)
396                         BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
397
398                 /* do not return this loop if clipped, we want every character tested */
399                 blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
400
401                 pen_x += g->advance_i;
402                 g_prev = g;
403                 c_prev = c;
404         }
405
406         blf_batch_draw_end();
407
408         if (r_info) {
409                 r_info->lines = 1;
410                 r_info->width = pen_x;
411         }
412 }
413 void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
414 {
415         blf_font_draw_ex(font, str, len, r_info, 0);
416 }
417
418 /* faster version of blf_font_draw, ascii only for view dimensions */
419 static void blf_font_draw_ascii_ex(
420         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
421         int pen_y)
422 {
423         unsigned char c;
424         GlyphBLF *g, *g_prev = NULL;
425         FT_Vector delta;
426         int pen_x = 0;
427         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
428
429         BLF_KERNING_VARS(font, has_kerning, kern_mode);
430
431         blf_font_ensure_ascii_table(font);
432
433         blf_batch_draw_begin(font);
434
435         while ((c = *(str++)) && len--) {
436                 BLI_assert(c < 128);
437                 if ((g = glyph_ascii_table[c]) == NULL)
438                         continue;
439                 if (has_kerning)
440                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
441
442                 /* do not return this loop if clipped, we want every character tested */
443                 blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
444
445                 pen_x += g->advance_i;
446                 g_prev = g;
447         }
448
449         blf_batch_draw_end();
450
451         if (r_info) {
452                 r_info->lines = 1;
453                 r_info->width = pen_x;
454         }
455 }
456 void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
457 {
458         blf_font_draw_ascii_ex(font, str, len, r_info, 0);
459 }
460
461 /* use fixed column width, but an utf8 character may occupy multiple columns */
462 int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
463 {
464         unsigned int c;
465         GlyphBLF *g;
466         int col, columns = 0;
467         int pen_x = 0, pen_y = 0;
468         size_t i = 0;
469         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
470
471         blf_font_ensure_ascii_table(font);
472
473         blf_batch_draw_begin(font);
474
475         while ((i < len) && str[i]) {
476                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
477
478                 if (UNLIKELY(c == BLI_UTF8_ERR))
479                         break;
480                 if (UNLIKELY(g == NULL))
481                         continue;
482
483                 /* do not return this loop if clipped, we want every character tested */
484                 blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
485
486                 col = BLI_wcwidth((wchar_t)c);
487                 if (col < 0)
488                         col = 1;
489
490                 columns += col;
491                 pen_x += cwidth * col;
492         }
493
494         blf_batch_draw_end();
495
496         return columns;
497 }
498
499 /* Sanity checks are done by BLF_draw_buffer() */
500 static void blf_font_draw_buffer_ex(
501         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
502         int pen_y)
503 {
504         unsigned int c;
505         GlyphBLF *g, *g_prev = NULL;
506         FT_Vector delta;
507         int pen_x = (int)font->pos[0];
508         int pen_y_basis = (int)font->pos[1] + pen_y;
509         size_t i = 0;
510         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
511
512         /* buffer specific vars */
513         FontBufInfoBLF *buf_info = &font->buf_info;
514         const float *b_col_float = buf_info->col_float;
515         const unsigned char *b_col_char = buf_info->col_char;
516         int chx, chy;
517         int y, x;
518
519         BLF_KERNING_VARS(font, has_kerning, kern_mode);
520
521         blf_font_ensure_ascii_table(font);
522
523         /* another buffer specific call for color conversion */
524
525         while ((i < len) && str[i]) {
526                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
527
528                 if (UNLIKELY(c == BLI_UTF8_ERR))
529                         break;
530                 if (UNLIKELY(g == NULL))
531                         continue;
532                 if (has_kerning)
533                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
534
535                 chx = pen_x + ((int)g->pos_x);
536                 chy = pen_y_basis + g->height;
537
538                 if (g->pitch < 0) {
539                         pen_y = pen_y_basis + (g->height - (int)g->pos_y);
540                 }
541                 else {
542                         pen_y = pen_y_basis - (g->height - (int)g->pos_y);
543                 }
544
545                 if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) {
546                         /* don't draw beyond the buffer bounds */
547                         int width_clip = g->width;
548                         int height_clip = g->height;
549                         int yb_start = g->pitch < 0 ? 0 : g->height - 1;
550
551                         if (width_clip + chx > buf_info->w)
552                                 width_clip -= chx + width_clip - buf_info->w;
553                         if (height_clip + pen_y > buf_info->h)
554                                 height_clip -= pen_y + height_clip - buf_info->h;
555                         
556                         /* drawing below the image? */
557                         if (pen_y < 0) {
558                                 yb_start += (g->pitch < 0) ? -pen_y : pen_y;
559                                 height_clip += pen_y;
560                                 pen_y = 0;
561                         }
562
563                         if (buf_info->fbuf) {
564                                 int yb = yb_start;
565                                 for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
566                                         for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
567                                                 const char a_byte = *(g->bitmap + x + (yb * g->pitch));
568                                                 if (a_byte) {
569                                                         const float a = (a_byte / 255.0f) * b_col_float[3];
570                                                         const size_t buf_ofs = (
571                                                                 ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
572                                                                 (size_t)buf_info->ch);
573                                                         float *fbuf = buf_info->fbuf + buf_ofs;
574
575                                                         if (a >= 1.0f) {
576                                                                 fbuf[0] = b_col_float[0];
577                                                                 fbuf[1] = b_col_float[1];
578                                                                 fbuf[2] = b_col_float[2];
579                                                                 fbuf[3] = 1.0f;
580                                                         }
581                                                         else {
582                                                                 fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a));
583                                                                 fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a));
584                                                                 fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a));
585                                                                 fbuf[3] = MIN2(fbuf[3] + a, 1.0f); /* clamp to 1.0 */
586                                                         }
587                                                 }
588                                         }
589
590                                         if (g->pitch < 0)
591                                                 yb++;
592                                         else
593                                                 yb--;
594                                 }
595                         }
596
597                         if (buf_info->cbuf) {
598                                 int yb = yb_start;
599                                 for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
600                                         for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
601                                                 const char a_byte = *(g->bitmap + x + (yb * g->pitch));
602
603                                                 if (a_byte) {
604                                                         const float a = (a_byte / 255.0f) * b_col_float[3];
605                                                         const size_t buf_ofs = (
606                                                                 ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
607                                                                 (size_t)buf_info->ch);
608                                                         unsigned char *cbuf = buf_info->cbuf + buf_ofs;
609
610                                                         if (a >= 1.0f) {
611                                                                 cbuf[0] = b_col_char[0];
612                                                                 cbuf[1] = b_col_char[1];
613                                                                 cbuf[2] = b_col_char[2];
614                                                                 cbuf[3] = 255;
615                                                         }
616                                                         else {
617                                                                 cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a)));
618                                                                 cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a)));
619                                                                 cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a)));
620                                                                 cbuf[3] = (unsigned char)MIN2((int)cbuf[3] + (int)(a * 255), 255); /* clamp to 255 */
621                                                         }
622                                                 }
623                                         }
624
625                                         if (g->pitch < 0)
626                                                 yb++;
627                                         else
628                                                 yb--;
629                                 }
630                         }
631                 }
632
633                 pen_x += g->advance_i;
634                 g_prev = g;
635         }
636
637         if (r_info) {
638                 r_info->lines = 1;
639                 r_info->width = pen_x;
640         }
641 }
642 void blf_font_draw_buffer(
643         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
644 {
645         blf_font_draw_buffer_ex(font, str, len, r_info, 0);
646 }
647
648 size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
649 {
650         unsigned int c;
651         GlyphBLF *g, *g_prev = NULL;
652         FT_Vector delta;
653         int pen_x = 0;
654         size_t i = 0, i_prev;
655         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
656         const int width_i = (int)width + 1;
657         int width_new;
658
659         BLF_KERNING_VARS(font, has_kerning, kern_mode);
660
661         blf_font_ensure_ascii_table(font);
662
663         while ((void)(i_prev = i),
664                (void)(width_new = pen_x),
665                ((i < len) && str[i]))
666         {
667                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
668
669                 if (UNLIKELY(c == BLI_UTF8_ERR))
670                         break;
671                 if (UNLIKELY(g == NULL))
672                         continue;
673                 if (has_kerning)
674                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
675
676                 pen_x += g->advance_i;
677
678                 if (width_i < pen_x) {
679                         break;
680                 }
681
682                 g_prev = g;
683         }
684
685         if (r_width) {
686                 *r_width = (float)width_new;
687         }
688
689         return i_prev;
690 }
691
692 size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
693 {
694         unsigned int c;
695         GlyphBLF *g, *g_prev = NULL;
696         FT_Vector delta;
697         int pen_x = 0;
698         size_t i = 0, i_prev;
699         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
700         const int width_i = (int)width + 1;
701         int width_new;
702
703         bool is_malloc;
704         int (*width_accum)[2];
705         int width_accum_ofs = 0;
706
707         BLF_KERNING_VARS(font, has_kerning, kern_mode);
708
709         /* skip allocs in simple cases */
710         len = BLI_strnlen(str, len);
711         if (width_i <= 1 || len == 0) {
712                 if (r_width) {
713                         *r_width = 0.0f;
714                 }
715                 return len;
716         }
717
718         if (len < 2048) {
719                 width_accum = BLI_array_alloca(width_accum, len);
720                 is_malloc = false;
721         }
722         else {
723                 width_accum = MEM_mallocN(sizeof(*width_accum) * len, __func__);
724                 is_malloc = true;
725         }
726
727         blf_font_ensure_ascii_table(font);
728
729         while ((i < len) && str[i]) {
730                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
731
732                 if (UNLIKELY(c == BLI_UTF8_ERR))
733                         break;
734                 if (UNLIKELY(g == NULL))
735                         continue;
736                 if (has_kerning)
737                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
738
739                 pen_x += g->advance_i;
740
741                 width_accum[width_accum_ofs][0] = (int)i;
742                 width_accum[width_accum_ofs][1] = pen_x;
743                 width_accum_ofs++;
744
745                 g_prev = g;
746         }
747
748         if (pen_x > width_i && width_accum_ofs != 0) {
749                 const int min_x = pen_x - width_i;
750
751                 /* search backwards */
752                 width_new = pen_x;
753                 while (width_accum_ofs-- > 0) {
754                         if (min_x > width_accum[width_accum_ofs][1]) {
755                                 break;
756                         }
757                 }
758                 width_accum_ofs++;
759                 width_new = pen_x - width_accum[width_accum_ofs][1];
760                 i_prev = (size_t)width_accum[width_accum_ofs][0];
761         }
762         else {
763                 width_new = pen_x;
764                 i_prev = 0;
765         }
766
767         if (is_malloc) {
768                 MEM_freeN(width_accum);
769         }
770
771         if (r_width) {
772                 *r_width = (float)width_new;
773         }
774
775         return i_prev;
776 }
777
778 static void blf_font_boundbox_ex(
779         FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info,
780         int pen_y)
781 {
782         unsigned int c, c_prev = BLI_UTF8_ERR;
783         GlyphBLF *g, *g_prev = NULL;
784         int pen_x = 0;
785         size_t i = 0;
786         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
787
788         rctf gbox;
789
790         BLF_KERNING_VARS(font, has_kerning, kern_mode);
791
792         box->xmin = 32000.0f;
793         box->xmax = -32000.0f;
794         box->ymin = 32000.0f;
795         box->ymax = -32000.0f;
796
797         blf_font_ensure_ascii_table(font);
798         blf_font_ensure_ascii_kerning(font, kern_mode);
799
800         while ((i < len) && str[i]) {
801                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
802
803                 if (UNLIKELY(c == BLI_UTF8_ERR))
804                         break;
805                 if (UNLIKELY(g == NULL))
806                         continue;
807                 if (has_kerning)
808                         BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
809
810                 gbox.xmin = (float)pen_x;
811                 gbox.xmax = (float)pen_x + g->advance;
812                 gbox.ymin = g->box.ymin + (float)pen_y;
813                 gbox.ymax = g->box.ymax + (float)pen_y;
814
815                 if (gbox.xmin < box->xmin) box->xmin = gbox.xmin;
816                 if (gbox.ymin < box->ymin) box->ymin = gbox.ymin;
817
818                 if (gbox.xmax > box->xmax) box->xmax = gbox.xmax;
819                 if (gbox.ymax > box->ymax) box->ymax = gbox.ymax;
820
821                 pen_x += g->advance_i;
822                 g_prev = g;
823                 c_prev = c;
824         }
825
826         if (box->xmin > box->xmax) {
827                 box->xmin = 0.0f;
828                 box->ymin = 0.0f;
829                 box->xmax = 0.0f;
830                 box->ymax = 0.0f;
831         }
832
833         if (r_info) {
834                 r_info->lines = 1;
835                 r_info->width = pen_x;
836         }
837 }
838 void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
839 {
840         blf_font_boundbox_ex(font, str, len, r_box, r_info, 0);
841 }
842
843
844 /* -------------------------------------------------------------------- */
845 /** \name Word-Wrap Support
846  * \{ */
847
848
849 /**
850  * Generic function to add word-wrap support for other existing functions.
851  *
852  * Wraps on spaces and respects newlines.
853  * Intentionally ignores non-unix newlines, tabs and more advanced text formatting.
854  *
855  * \note If we want rich text - we better have a higher level API to handle that
856  * (color, bold, switching fonts... etc).
857  */
858 static void blf_font_wrap_apply(
859         FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
860         void (*callback)(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata),
861         void *userdata)
862 {
863         unsigned int c;
864         GlyphBLF *g, *g_prev = NULL;
865         FT_Vector delta;
866         int pen_x = 0, pen_y = 0;
867         size_t i = 0;
868         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
869         int lines = 0;
870         int pen_x_next = 0;
871
872         BLF_KERNING_VARS(font, has_kerning, kern_mode);
873
874         struct WordWrapVars {
875                 int wrap_width;
876                 size_t start, last[2];
877         } wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}};
878
879         blf_font_ensure_ascii_table(font);
880         // printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
881         while ((i < len) && str[i]) {
882
883                 /* wrap vars */
884                 size_t i_curr = i;
885                 bool do_draw = false;
886
887                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
888
889                 if (UNLIKELY(c == BLI_UTF8_ERR))
890                         break;
891                 if (UNLIKELY(g == NULL))
892                         continue;
893                 if (has_kerning)
894                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
895
896                 /**
897                  * Implementation Detail (utf8).
898                  *
899                  * Take care with single byte offsets here,
900                  * since this is utf8 we can't be sure a single byte is a single character.
901                  *
902                  * This is _only_ done when we know for sure the character is ascii (newline or a space).
903                  */
904                 pen_x_next = pen_x + g->advance_i;
905                 if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
906                         do_draw = true;
907                 }
908                 else if (UNLIKELY(((i < len) && str[i]) == 0)) {
909                         /* need check here for trailing newline, else we draw it */
910                         wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
911                         wrap.last[1] = i;
912                         do_draw = true;
913                 }
914                 else if (UNLIKELY(g->c == '\n')) {
915                         wrap.last[0] = i_curr + 1;
916                         wrap.last[1] = i;
917                         do_draw = true;
918                 }
919                 else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) {
920                         wrap.last[0] = i_curr;
921                         wrap.last[1] = i_curr;
922                 }
923
924                 if (UNLIKELY(do_draw)) {
925                         // printf("(%03d..%03d)  `%.*s`\n",
926                         //        wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]);
927
928                         callback(font, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata);
929                         wrap.start = wrap.last[0];
930                         i = wrap.last[1];
931                         pen_x = 0;
932                         pen_y -= font->glyph_cache->glyph_height_max;
933                         g_prev = NULL;
934                         lines += 1;
935                         continue;
936                 }
937
938                 pen_x = pen_x_next;
939                 g_prev = g;
940         }
941
942         // printf("done! lines: %d, width, %d\n", lines, pen_x_next);
943
944         if (r_info) {
945                 r_info->lines = lines;
946                 /* width of last line only (with wrapped lines) */
947                 r_info->width = pen_x_next;
948         }
949 }
950
951 /* blf_font_draw__wrap */
952 static void blf_font_draw__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
953 {
954         blf_font_draw_ex(font, str, len, NULL, pen_y);
955 }
956 void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
957 {
958         blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL);
959 }
960
961 /* blf_font_boundbox__wrap */
962 static void blf_font_boundbox_wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata)
963 {
964         rctf *box = userdata;
965         rctf box_single;
966
967         blf_font_boundbox_ex(font, str, len, &box_single, NULL, pen_y);
968         BLI_rctf_union(box, &box_single);
969 }
970 void blf_font_boundbox__wrap(FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info)
971 {
972         box->xmin = 32000.0f;
973         box->xmax = -32000.0f;
974         box->ymin = 32000.0f;
975         box->ymax = -32000.0f;
976
977         blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box);
978 }
979
980 /* blf_font_draw_buffer__wrap */
981 static void blf_font_draw_buffer__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
982 {
983         blf_font_draw_buffer_ex(font, str, len, NULL, pen_y);
984 }
985 void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
986 {
987         blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
988 }
989
990 /** \} */
991
992
993 void blf_font_width_and_height(
994         FontBLF *font, const char *str, size_t len,
995         float *r_width, float *r_height, struct ResultBLF *r_info)
996 {
997         float xa, ya;
998         rctf box;
999
1000         if (font->flags & BLF_ASPECT) {
1001                 xa = font->aspect[0];
1002                 ya = font->aspect[1];
1003         }
1004         else {
1005                 xa = 1.0f;
1006                 ya = 1.0f;
1007         }
1008
1009         if (font->flags & BLF_WORD_WRAP) {
1010                 blf_font_boundbox__wrap(font, str, len, &box, r_info);
1011         }
1012         else {
1013                 blf_font_boundbox(font, str, len, &box, r_info);
1014         }
1015         *r_width  = (BLI_rctf_size_x(&box) * xa);
1016         *r_height = (BLI_rctf_size_y(&box) * ya);
1017 }
1018
1019 float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
1020 {
1021         float xa;
1022         rctf box;
1023
1024         if (font->flags & BLF_ASPECT)
1025                 xa = font->aspect[0];
1026         else
1027                 xa = 1.0f;
1028
1029         if (font->flags & BLF_WORD_WRAP) {
1030                 blf_font_boundbox__wrap(font, str, len, &box, r_info);
1031         }
1032         else {
1033                 blf_font_boundbox(font, str, len, &box, r_info);
1034         }
1035         return BLI_rctf_size_x(&box) * xa;
1036 }
1037
1038 float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
1039 {
1040         float ya;
1041         rctf box;
1042
1043         if (font->flags & BLF_ASPECT)
1044                 ya = font->aspect[1];
1045         else
1046                 ya = 1.0f;
1047
1048         if (font->flags & BLF_WORD_WRAP) {
1049                 blf_font_boundbox__wrap(font, str, len, &box, r_info);
1050         }
1051         else {
1052                 blf_font_boundbox(font, str, len, &box, r_info);
1053         }
1054         return BLI_rctf_size_y(&box) * ya;
1055 }
1056
1057 float blf_font_fixed_width(FontBLF *font)
1058 {
1059         const unsigned int c = ' ';
1060         GlyphBLF *g = blf_glyph_search(font->glyph_cache, c);
1061         if (!g) {
1062                 g = blf_glyph_add(font, FT_Get_Char_Index(font->face, c), c);
1063
1064                 /* if we don't find the glyph. */
1065                 if (!g) {
1066                         return 0.0f;
1067                 }
1068         }
1069
1070         return g->advance;
1071 }
1072
1073 int blf_font_count_missing_chars(FontBLF *font, const char *str, const size_t len, int *r_tot_chars)
1074 {
1075         int missing = 0;
1076         size_t i = 0;
1077
1078         *r_tot_chars = 0;
1079         while (i < len) {
1080                 unsigned int c;
1081
1082                 if ((c = str[i]) < 0x80) {
1083                         i++;
1084                 }
1085                 else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
1086                         if (FT_Get_Char_Index((font)->face, c) == 0) {
1087                                 missing++;
1088                         }
1089                 }
1090                 (*r_tot_chars)++;
1091         }
1092         return missing;
1093 }
1094
1095 void blf_font_free(FontBLF *font)
1096 {
1097         GlyphCacheBLF *gc;
1098
1099         font->glyph_cache = NULL;
1100         while ((gc = BLI_pophead(&font->cache))) {
1101                 blf_glyph_cache_free(gc);
1102         }
1103
1104         blf_kerning_cache_clear(font);
1105
1106         FT_Done_Face(font->face);
1107         if (font->filename)
1108                 MEM_freeN(font->filename);
1109         if (font->name)
1110                 MEM_freeN(font->name);
1111         MEM_freeN(font);
1112 }
1113
1114 static void blf_font_fill(FontBLF *font)
1115 {
1116         font->aspect[0] = 1.0f;
1117         font->aspect[1] = 1.0f;
1118         font->aspect[2] = 1.0f;
1119         font->pos[0] = 0.0f;
1120         font->pos[1] = 0.0f;
1121         font->angle = 0.0f;
1122
1123         for (int i = 0; i < 16; i++)
1124                 font->m[i] = 0;
1125
1126         /* annoying bright color so we can see where to add BLF_color calls */
1127         font->color[0] = 255;
1128         font->color[1] = 255;
1129         font->color[2] = 0;
1130         font->color[3] = 255;
1131
1132         font->clip_rec.xmin = 0.0f;
1133         font->clip_rec.xmax = 0.0f;
1134         font->clip_rec.ymin = 0.0f;
1135         font->clip_rec.ymax = 0.0f;
1136         font->flags = 0;
1137         font->dpi = 0;
1138         font->size = 0;
1139         BLI_listbase_clear(&font->cache);
1140         BLI_listbase_clear(&font->kerning_caches);
1141         font->glyph_cache = NULL;
1142         font->kerning_cache = NULL;
1143 #if BLF_BLUR_ENABLE
1144         font->blur = 0;
1145 #endif
1146         font->tex_size_max = -1;
1147
1148         font->buf_info.fbuf = NULL;
1149         font->buf_info.cbuf = NULL;
1150         font->buf_info.w = 0;
1151         font->buf_info.h = 0;
1152         font->buf_info.ch = 0;
1153         font->buf_info.col_init[0] = 0;
1154         font->buf_info.col_init[1] = 0;
1155         font->buf_info.col_init[2] = 0;
1156         font->buf_info.col_init[3] = 0;
1157
1158         font->ft_lib = ft_lib;
1159         font->ft_lib_mutex = &ft_lib_mutex;
1160 }
1161
1162 FontBLF *blf_font_new(const char *name, const char *filename)
1163 {
1164         FontBLF *font;
1165         FT_Error err;
1166         char *mfile;
1167
1168         font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
1169         err = FT_New_Face(ft_lib, filename, 0, &font->face);
1170         if (err) {
1171                 MEM_freeN(font);
1172                 return NULL;
1173         }
1174
1175         err = FT_Select_Charmap(font->face, ft_encoding_unicode);
1176         if (err) {
1177                 printf("Can't set the unicode character map!\n");
1178                 FT_Done_Face(font->face);
1179                 MEM_freeN(font);
1180                 return NULL;
1181         }
1182
1183         mfile = blf_dir_metrics_search(filename);
1184         if (mfile) {
1185                 err = FT_Attach_File(font->face, mfile);
1186                 if (err) {
1187                         fprintf(stderr, "FT_Attach_File failed to load '%s' with error %d\n", filename, (int)err);
1188                 }
1189                 MEM_freeN(mfile);
1190         }
1191
1192         font->name = BLI_strdup(name);
1193         font->filename = BLI_strdup(filename);
1194         blf_font_fill(font);
1195         return font;
1196 }
1197
1198 void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
1199 {
1200         FT_Open_Args open;
1201
1202         open.flags = FT_OPEN_MEMORY;
1203         open.memory_base = (const FT_Byte *)mem;
1204         open.memory_size = mem_size;
1205         FT_Attach_Stream(font->face, &open);
1206 }
1207
1208 FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
1209 {
1210         FontBLF *font;
1211         FT_Error err;
1212
1213         font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new_from_mem");
1214         err = FT_New_Memory_Face(ft_lib, mem, mem_size, 0, &font->face);
1215         if (err) {
1216                 MEM_freeN(font);
1217                 return NULL;
1218         }
1219
1220         err = FT_Select_Charmap(font->face, ft_encoding_unicode);
1221         if (err) {
1222                 printf("Can't set the unicode character map!\n");
1223                 FT_Done_Face(font->face);
1224                 MEM_freeN(font);
1225                 return NULL;
1226         }
1227
1228         font->name = BLI_strdup(name);
1229         font->filename = NULL;
1230         blf_font_fill(font);
1231         return font;
1232 }