Blender  V3.3
blf_font.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation. All rights reserved. */
3 
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <ft2build.h>
18 
19 #include FT_FREETYPE_H
20 #include FT_GLYPH_H
21 #include FT_TRUETYPE_TABLES_H /* For TT_OS2 */
22 #include FT_MULTIPLE_MASTERS_H /* Variable font support. */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "DNA_vec_types.h"
27 
28 #include "BLI_listbase.h"
29 #include "BLI_math.h"
30 #include "BLI_math_color_blend.h"
31 #include "BLI_rect.h"
32 #include "BLI_string.h"
33 #include "BLI_string_utf8.h"
34 #include "BLI_threads.h"
35 
36 #include "BLF_api.h"
37 
38 #include "GPU_batch.h"
39 #include "GPU_matrix.h"
40 
41 #include "blf_internal.h"
42 #include "blf_internal_types.h"
43 
44 #include "BLI_strict_flags.h"
45 
46 #ifdef WIN32
47 # define FT_New_Face FT_New_Face__win32_compat
48 #endif
49 
50 /* Batching buffer for drawing. */
51 
53 
54 /* freetype2 handle ONLY for this file! */
55 static FT_Library ft_lib;
58 
59 /* May be set to #UI_widgetbase_draw_cache_flush. */
61 
62 static ft_pix blf_font_height_max_ft_pix(struct FontBLF *font);
63 static ft_pix blf_font_width_max_ft_pix(struct FontBLF *font);
64 
65 /* -------------------------------------------------------------------- */
69 /* Convert a FreeType 26.6 value representing an unscaled design size to factional pixels. */
70 static ft_pix blf_unscaled_F26Dot6_to_pixels(FontBLF *font, FT_Pos value)
71 {
72  /* Scale value by font size using integer-optimized multiplication. */
73  FT_Long scaled = FT_MulFix(value, font->face->size->metrics.x_scale);
74 
75  /* Copied from FreeType's FT_Get_Kerning (with FT_KERNING_DEFAULT), scaling down */
76  /* kerning distances at small ppem values so that they don't become too big. */
77  if (font->face->size->metrics.x_ppem < 25) {
78  scaled = FT_MulDiv(scaled, font->face->size->metrics.x_ppem, 25);
79  }
80 
81  return (ft_pix)scaled;
82 }
83 
86 /* -------------------------------------------------------------------- */
96 static void blf_batch_draw_init(void)
97 {
98  GPUVertFormat format = {0};
104  &format, "glyph_size", GPU_COMP_I32, 2, GPU_FETCH_INT);
105 
108 
113  g_batch.glyph_len = 0;
114 
115  /* A dummy VBO containing 4 points, attributes are not used. */
117  GPU_vertbuf_data_alloc(vbo, 4);
118 
119  /* We render a quad as a triangle strip and instance it for each glyph. */
122 }
123 
124 static void blf_batch_draw_exit(void)
125 {
127 }
128 
130 {
131  if (g_batch.batch == NULL) {
133  }
134 
135  const bool font_changed = (g_batch.font != font);
136  const bool simple_shader = ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0);
137  const bool shader_changed = (simple_shader != g_batch.simple_shader);
138 
139  g_batch.active = g_batch.enabled && simple_shader;
140 
141  if (simple_shader) {
142  /* Offset is applied to each glyph. */
143  g_batch.ofs[0] = font->pos[0];
144  g_batch.ofs[1] = font->pos[1];
145  }
146  else {
147  /* Offset is baked in modelview mat. */
149  }
150 
151  if (g_batch.active) {
152  float gpumat[4][4];
154 
155  bool mat_changed = (memcmp(gpumat, g_batch.mat, sizeof(g_batch.mat)) != 0);
156 
157  if (mat_changed) {
158  /* Modelviewmat is no longer the same.
159  * Flush cache but with the previous mat. */
160  GPU_matrix_push();
162  }
163 
164  /* flush cache if config is not the same. */
165  if (mat_changed || font_changed || shader_changed) {
166  blf_batch_draw();
167  g_batch.simple_shader = simple_shader;
168  g_batch.font = font;
169  }
170  else {
171  /* Nothing changed continue batching. */
172  return;
173  }
174 
175  if (mat_changed) {
176  GPU_matrix_pop();
177  /* Save for next memcmp. */
178  memcpy(g_batch.mat, gpumat, sizeof(g_batch.mat));
179  }
180  }
181  else {
182  /* flush cache */
183  blf_batch_draw();
184  g_batch.font = font;
185  g_batch.simple_shader = simple_shader;
186  }
187 }
188 
190 {
192  BLI_assert(gc);
193  BLI_assert(gc->bitmap_len > 0);
194 
195  if (gc->bitmap_len > gc->bitmap_len_landed) {
196  const int tex_width = GPU_texture_width(gc->texture);
197 
198  int bitmap_len_landed = gc->bitmap_len_landed;
199  int remain = gc->bitmap_len - bitmap_len_landed;
200  int offset_x = bitmap_len_landed % tex_width;
201  int offset_y = bitmap_len_landed / tex_width;
202 
203  /* TODO(germano): Update more than one row in a single call. */
204  while (remain) {
205  int remain_row = tex_width - offset_x;
206  int width = remain > remain_row ? remain_row : remain;
209  &gc->bitmap_result[bitmap_len_landed],
210  offset_x,
211  offset_y,
212  0,
213  width,
214  1,
215  0);
216 
217  bitmap_len_landed += width;
218  remain -= width;
219  offset_x = 0;
220  offset_y += 1;
221  }
222 
223  gc->bitmap_len_landed = bitmap_len_landed;
224  }
225 
226  return gc->texture;
227 }
228 
229 void blf_batch_draw(void)
230 {
231  if (g_batch.glyph_len == 0) {
232  return;
233  }
234 
236 
237  /* We need to flush widget base first to ensure correct ordering. */
238  if (blf_draw_cache_flush != NULL) {
240  }
241 
244  GPU_vertbuf_use(g_batch.verts); /* send data */
245 
247  GPU_batch_texture_bind(g_batch.batch, "glyph", texture);
249 
251 
252  GPU_texture_unbind(texture);
253 
254  /* restart to 1st vertex data pointers */
259  g_batch.glyph_len = 0;
260 }
261 
262 static void blf_batch_draw_end(void)
263 {
264  if (!g_batch.active) {
265  blf_batch_draw();
266  }
267 }
268 
271 /* -------------------------------------------------------------------- */
275 /* Fast path for runs of ASCII characters. Given that common UTF-8
276  * input will consist of an overwhelming majority of ASCII
277  * characters.
278  */
279 
281  FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p)
282 {
283  uint charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
284  /* Invalid unicode sequences return the byte value, stepping forward one.
285  * This allows `latin1` to display (which is sometimes used for file-paths). */
286  BLI_assert(charcode != BLI_UTF8_ERR);
287  return blf_glyph_ensure(font, gc, charcode);
288 }
289 
290 BLI_INLINE ft_pix blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const GlyphBLF *g)
291 {
292  ft_pix adjustment = 0;
293 
294  /* Small adjust if there is hinting. */
295  adjustment += g->lsb_delta - ((g_prev) ? g_prev->rsb_delta : 0);
296 
297  if (FT_HAS_KERNING(font->face) && g_prev) {
298  FT_Vector delta = {KERNING_ENTRY_UNSET};
299 
300  /* Get unscaled kerning value from our cache if ASCII. */
301  if ((g_prev->c < KERNING_CACHE_TABLE_SIZE) && (g->c < GLYPH_ASCII_TABLE_SIZE)) {
302  delta.x = font->kerning_cache->ascii_table[g->c][g_prev->c];
303  }
304 
305  /* If not ASCII or not found in cache, ask FreeType for kerning. */
306  if (UNLIKELY(delta.x == KERNING_ENTRY_UNSET)) {
307  /* Note that this function sets delta values to zero on any error. */
308  FT_Get_Kerning(font->face, g_prev->idx, g->idx, FT_KERNING_UNSCALED, &delta);
309  }
310 
311  /* If ASCII we save this value to our cache for quicker access next time. */
312  if ((g_prev->c < KERNING_CACHE_TABLE_SIZE) && (g->c < GLYPH_ASCII_TABLE_SIZE)) {
313  font->kerning_cache->ascii_table[g->c][g_prev->c] = (int)delta.x;
314  }
315 
316  if (delta.x != 0) {
317  /* Convert unscaled design units to pixels and move pen. */
318  adjustment += blf_unscaled_F26Dot6_to_pixels(font, delta.x);
319  }
320  }
321 
322  return adjustment;
323 }
324 
327 /* -------------------------------------------------------------------- */
331 static void blf_font_draw_ex(FontBLF *font,
332  GlyphCacheBLF *gc,
333  const char *str,
334  const size_t str_len,
335  struct ResultBLF *r_info,
336  ft_pix pen_y)
337 {
338  GlyphBLF *g, *g_prev = NULL;
339  ft_pix pen_x = 0;
340  size_t i = 0;
341 
342  if (str_len == 0) {
343  /* early output, don't do any IMM OpenGL. */
344  return;
345  }
346 
347  blf_batch_draw_begin(font);
348 
349  while ((i < str_len) && str[i]) {
350  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
351 
352  if (UNLIKELY(g == NULL)) {
353  continue;
354  }
355  pen_x += blf_kerning(font, g_prev, g);
356 
357  /* do not return this loop if clipped, we want every character tested */
358  blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y));
359 
360  pen_x = ft_pix_round_advance(pen_x, g->advance_x);
361  g_prev = g;
362  }
363 
365 
366  if (r_info) {
367  r_info->lines = 1;
368  r_info->width = ft_pix_to_int(pen_x);
369  }
370 }
371 void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
372 {
374  blf_font_draw_ex(font, gc, str, str_len, r_info, 0);
376 }
377 
378 int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
379 {
380  GlyphBLF *g;
381  int col, columns = 0;
382  ft_pix pen_x = 0, pen_y = 0;
383  ft_pix cwidth_fpx = ft_pix_from_int(cwidth);
384 
385  size_t i = 0;
386 
388 
389  blf_batch_draw_begin(font);
390 
391  while ((i < str_len) && str[i]) {
392  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
393 
394  if (UNLIKELY(g == NULL)) {
395  continue;
396  }
397  /* do not return this loop if clipped, we want every character tested */
398  blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y));
399 
400  col = BLI_wcwidth((char32_t)g->c);
401  if (col < 0) {
402  col = 1;
403  }
404 
405  columns += col;
406  pen_x += cwidth_fpx * col;
407  }
408 
410 
412  return columns;
413 }
414 
417 /* -------------------------------------------------------------------- */
421 /* Sanity checks are done by BLF_draw_buffer() */
423  GlyphCacheBLF *gc,
424  const char *str,
425  const size_t str_len,
426  struct ResultBLF *r_info,
427  ft_pix pen_y)
428 {
429  GlyphBLF *g, *g_prev = NULL;
430  ft_pix pen_x = ft_pix_from_int(font->pos[0]);
431  ft_pix pen_y_basis = ft_pix_from_int(font->pos[1]) + pen_y;
432  size_t i = 0;
433 
434  /* buffer specific vars */
435  FontBufInfoBLF *buf_info = &font->buf_info;
436  const float *b_col_float = buf_info->col_float;
437  const unsigned char *b_col_char = buf_info->col_char;
438  int chx, chy;
439  int y, x;
440 
441  /* another buffer specific call for color conversion */
442 
443  while ((i < str_len) && str[i]) {
444  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
445 
446  if (UNLIKELY(g == NULL)) {
447  continue;
448  }
449  pen_x += blf_kerning(font, g_prev, g);
450 
451  chx = ft_pix_to_int(pen_x + ft_pix_from_int(g->pos[0]));
452  chy = ft_pix_to_int(pen_y_basis + ft_pix_from_int(g->dims[1]));
453 
454  if (g->pitch < 0) {
455  pen_y = pen_y_basis + ft_pix_from_int(g->dims[1] - g->pos[1]);
456  }
457  else {
458  pen_y = pen_y_basis - ft_pix_from_int(g->dims[1] - g->pos[1]);
459  }
460 
461  if ((chx + g->dims[0]) >= 0 && chx < buf_info->dims[0] &&
462  (ft_pix_to_int(pen_y) + g->dims[1]) >= 0 && ft_pix_to_int(pen_y) < buf_info->dims[1]) {
463  /* don't draw beyond the buffer bounds */
464  int width_clip = g->dims[0];
465  int height_clip = g->dims[1];
466  int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1;
467 
468  if (width_clip + chx > buf_info->dims[0]) {
469  width_clip -= chx + width_clip - buf_info->dims[0];
470  }
471  if (height_clip + ft_pix_to_int(pen_y) > buf_info->dims[1]) {
472  height_clip -= ft_pix_to_int(pen_y) + height_clip - buf_info->dims[1];
473  }
474 
475  /* drawing below the image? */
476  if (pen_y < 0) {
477  yb_start += (g->pitch < 0) ? -ft_pix_to_int(pen_y) : ft_pix_to_int(pen_y);
478  height_clip += ft_pix_to_int(pen_y);
479  pen_y = 0;
480  }
481 
482  /* Avoid conversions in the pixel writing loop. */
483  const int pen_y_px = ft_pix_to_int(pen_y);
484 
485  if (buf_info->fbuf) {
486  int yb = yb_start;
487  for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
488  for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
489  const char a_byte = *(g->bitmap + x + (yb * g->pitch));
490  if (a_byte) {
491  const float a = (a_byte / 255.0f) * b_col_float[3];
492  const size_t buf_ofs = (((size_t)(chx + x) +
493  ((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
494  (size_t)buf_info->ch);
495  float *fbuf = buf_info->fbuf + buf_ofs;
496 
497  float font_pixel[4];
498  font_pixel[0] = b_col_float[0] * a;
499  font_pixel[1] = b_col_float[1] * a;
500  font_pixel[2] = b_col_float[2] * a;
501  font_pixel[3] = a;
502  blend_color_mix_float(fbuf, fbuf, font_pixel);
503  }
504  }
505 
506  if (g->pitch < 0) {
507  yb++;
508  }
509  else {
510  yb--;
511  }
512  }
513  }
514 
515  if (buf_info->cbuf) {
516  int yb = yb_start;
517  for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
518  for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
519  const char a_byte = *(g->bitmap + x + (yb * g->pitch));
520 
521  if (a_byte) {
522  const float a = (a_byte / 255.0f) * b_col_float[3];
523  const size_t buf_ofs = (((size_t)(chx + x) +
524  ((size_t)(pen_y_px + y) * (size_t)buf_info->dims[0])) *
525  (size_t)buf_info->ch);
526  unsigned char *cbuf = buf_info->cbuf + buf_ofs;
527 
528  uchar font_pixel[4];
529  font_pixel[0] = b_col_char[0];
530  font_pixel[1] = b_col_char[1];
531  font_pixel[2] = b_col_char[2];
532  font_pixel[3] = unit_float_to_uchar_clamp(a);
533  blend_color_mix_byte(cbuf, cbuf, font_pixel);
534  }
535  }
536 
537  if (g->pitch < 0) {
538  yb++;
539  }
540  else {
541  yb--;
542  }
543  }
544  }
545  }
546 
547  pen_x = ft_pix_round_advance(pen_x, g->advance_x);
548  g_prev = g;
549  }
550 
551  if (r_info) {
552  r_info->lines = 1;
553  r_info->width = ft_pix_to_int(pen_x);
554  }
555 }
556 
558  const char *str,
559  const size_t str_len,
560  struct ResultBLF *r_info)
561 {
563  blf_font_draw_buffer_ex(font, gc, str, str_len, r_info, 0);
565 }
566 
569 /* -------------------------------------------------------------------- */
578  FontBLF *font, GlyphBLF *g_prev, GlyphBLF *g, ft_pix *pen_x, const int width_i)
579 {
580  if (UNLIKELY(g == NULL)) {
581  return false; /* continue the calling loop. */
582  }
583  *pen_x += blf_kerning(font, g_prev, g);
584  *pen_x = ft_pix_round_advance(*pen_x, g->advance_x);
585 
586  /* When true, break the calling loop. */
587  return (ft_pix_to_int(*pen_x) >= width_i);
588 }
589 
591  FontBLF *font, const char *str, const size_t str_len, int width, int *r_width)
592 {
593  GlyphBLF *g, *g_prev;
594  ft_pix pen_x;
595  ft_pix width_new;
596  size_t i, i_prev;
597 
599  const int width_i = (int)width;
600 
601  for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL; (i < str_len) && str[i];
602  i_prev = i, width_new = pen_x, g_prev = g) {
603  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
604 
605  if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width_i)) {
606  break;
607  }
608  }
609 
610  if (r_width) {
611  *r_width = ft_pix_to_int(width_new);
612  }
613 
615  return i_prev;
616 }
617 
619  FontBLF *font, const char *str, const size_t str_len, int width, int *r_width)
620 {
621  GlyphBLF *g, *g_prev;
622  ft_pix pen_x, width_new;
623  size_t i, i_prev, i_tmp;
624  const char *s, *s_prev;
625 
627 
628  i = BLI_strnlen(str, str_len);
630  i = (size_t)(s - str);
631  s_prev = BLI_str_find_prev_char_utf8(s, str);
632  i_prev = (size_t)(s_prev - str);
633 
634  i_tmp = i;
635  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp);
636  for (width_new = pen_x = 0; (s != NULL);
637  i = i_prev, s = s_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
638  s_prev = BLI_str_find_prev_char_utf8(s, str);
639  i_prev = (size_t)(s_prev - str);
640 
641  if (s_prev != NULL) {
642  i_tmp = i_prev;
643  g_prev = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp);
644  BLI_assert(i_tmp == i);
645  }
646 
647  if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width)) {
648  break;
649  }
650  }
651 
652  if (r_width) {
653  *r_width = ft_pix_to_int(width_new);
654  }
655 
657  return i;
658 }
659 
662 /* -------------------------------------------------------------------- */
666 static void blf_font_boundbox_ex(FontBLF *font,
667  GlyphCacheBLF *gc,
668  const char *str,
669  const size_t str_len,
670  rcti *box,
671  struct ResultBLF *r_info,
672  ft_pix pen_y)
673 {
674  GlyphBLF *g, *g_prev = NULL;
675  ft_pix pen_x = 0;
676  size_t i = 0;
677 
678  ft_pix box_xmin = ft_pix_from_int(32000);
679  ft_pix box_xmax = ft_pix_from_int(-32000);
680  ft_pix box_ymin = ft_pix_from_int(32000);
681  ft_pix box_ymax = ft_pix_from_int(-32000);
682 
683  while ((i < str_len) && str[i]) {
684  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
685 
686  if (UNLIKELY(g == NULL)) {
687  continue;
688  }
689  pen_x += blf_kerning(font, g_prev, g);
690  const ft_pix pen_x_next = ft_pix_round_advance(pen_x, g->advance_x);
691 
692  const ft_pix gbox_xmin = pen_x;
693  const ft_pix gbox_xmax = pen_x_next;
694  const ft_pix gbox_ymin = g->box_ymin + pen_y;
695  const ft_pix gbox_ymax = g->box_ymax + pen_y;
696 
697  if (gbox_xmin < box_xmin) {
698  box_xmin = gbox_xmin;
699  }
700  if (gbox_ymin < box_ymin) {
701  box_ymin = gbox_ymin;
702  }
703 
704  if (gbox_xmax > box_xmax) {
705  box_xmax = gbox_xmax;
706  }
707  if (gbox_ymax > box_ymax) {
708  box_ymax = gbox_ymax;
709  }
710 
711  pen_x = pen_x_next;
712  g_prev = g;
713  }
714 
715  if (box_xmin > box_xmax) {
716  box_xmin = 0;
717  box_ymin = 0;
718  box_xmax = 0;
719  box_ymax = 0;
720  }
721 
722  box->xmin = ft_pix_to_int_floor(box_xmin);
723  box->xmax = ft_pix_to_int_ceil(box_xmax);
724  box->ymin = ft_pix_to_int_floor(box_ymin);
725  box->ymax = ft_pix_to_int_ceil(box_ymax);
726 
727  if (r_info) {
728  r_info->lines = 1;
729  r_info->width = ft_pix_to_int(pen_x);
730  }
731 }
733  FontBLF *font, const char *str, const size_t str_len, rcti *r_box, struct ResultBLF *r_info)
734 {
736  blf_font_boundbox_ex(font, gc, str, str_len, r_box, r_info, 0);
738 }
739 
741  const char *str,
742  const size_t str_len,
743  float *r_width,
744  float *r_height,
745  struct ResultBLF *r_info)
746 {
747  float xa, ya;
748  rcti box;
749 
750  if (font->flags & BLF_ASPECT) {
751  xa = font->aspect[0];
752  ya = font->aspect[1];
753  }
754  else {
755  xa = 1.0f;
756  ya = 1.0f;
757  }
758 
759  if (font->flags & BLF_WORD_WRAP) {
760  blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
761  }
762  else {
763  blf_font_boundbox(font, str, str_len, &box, r_info);
764  }
765  *r_width = ((float)BLI_rcti_size_x(&box) * xa);
766  *r_height = ((float)BLI_rcti_size_y(&box) * ya);
767 }
768 
770  const char *str,
771  const size_t str_len,
772  struct ResultBLF *r_info)
773 {
774  float xa;
775  rcti box;
776 
777  if (font->flags & BLF_ASPECT) {
778  xa = font->aspect[0];
779  }
780  else {
781  xa = 1.0f;
782  }
783 
784  if (font->flags & BLF_WORD_WRAP) {
785  blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
786  }
787  else {
788  blf_font_boundbox(font, str, str_len, &box, r_info);
789  }
790  return (float)BLI_rcti_size_x(&box) * xa;
791 }
792 
794  const char *str,
795  const size_t str_len,
796  struct ResultBLF *r_info)
797 {
798  float ya;
799  rcti box;
800 
801  if (font->flags & BLF_ASPECT) {
802  ya = font->aspect[1];
803  }
804  else {
805  ya = 1.0f;
806  }
807 
808  if (font->flags & BLF_WORD_WRAP) {
809  blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
810  }
811  else {
812  blf_font_boundbox(font, str, str_len, &box, r_info);
813  }
814  return (float)BLI_rcti_size_y(&box) * ya;
815 }
816 
818 {
820  float width = (gc) ? (float)gc->fixed_width : font->size / 2.0f;
822  return width;
823 }
824 
826  GlyphCacheBLF *gc,
827  const char *str,
828  const size_t str_len,
829  BLF_GlyphBoundsFn user_fn,
830  void *user_data,
831  struct ResultBLF *r_info,
832  ft_pix pen_y)
833 {
834  GlyphBLF *g, *g_prev = NULL;
835  ft_pix pen_x = 0;
836  size_t i = 0, i_curr;
837  rcti gbox_px;
838 
839  if (str_len == 0) {
840  /* early output. */
841  return;
842  }
843 
844  while ((i < str_len) && str[i]) {
845  i_curr = i;
846  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
847 
848  if (UNLIKELY(g == NULL)) {
849  continue;
850  }
851  pen_x += blf_kerning(font, g_prev, g);
852  const ft_pix pen_x_next = ft_pix_round_advance(pen_x, g->advance_x);
853 
854  gbox_px.xmin = ft_pix_to_int_floor(pen_x);
855  gbox_px.xmax = ft_pix_to_int_ceil(pen_x_next);
856  gbox_px.ymin = ft_pix_to_int_floor(pen_y);
857  gbox_px.ymax = gbox_px.ymin - g->dims[1];
858  const int advance_x_px = gbox_px.xmax - gbox_px.xmin;
859 
860  pen_x = pen_x_next;
861 
862  rcti box_px;
863  box_px.xmin = ft_pix_to_int_floor(g->box_xmin);
864  box_px.xmax = ft_pix_to_int_ceil(g->box_xmax);
865  box_px.ymin = ft_pix_to_int_floor(g->box_ymin);
866  box_px.ymax = ft_pix_to_int_ceil(g->box_ymax);
867 
868  if (user_fn(str, i_curr, &gbox_px, advance_x_px, &box_px, g->pos, user_data) == false) {
869  break;
870  }
871 
872  g_prev = g;
873  }
874 
875  if (r_info) {
876  r_info->lines = 1;
877  r_info->width = ft_pix_to_int(pen_x);
878  }
879 }
881  const char *str,
882  const size_t str_len,
883  BLF_GlyphBoundsFn user_fn,
884  void *user_data,
885  struct ResultBLF *r_info)
886 {
888  blf_font_boundbox_foreach_glyph_ex(font, gc, str, str_len, user_fn, user_data, r_info, 0);
890 }
891 
894 /* -------------------------------------------------------------------- */
907 static void blf_font_wrap_apply(FontBLF *font,
908  const char *str,
909  const size_t str_len,
910  struct ResultBLF *r_info,
911  void (*callback)(FontBLF *font,
912  GlyphCacheBLF *gc,
913  const char *str,
914  const size_t str_len,
915  ft_pix pen_y,
916  void *userdata),
917  void *userdata)
918 {
919  GlyphBLF *g, *g_prev = NULL;
920  ft_pix pen_x = 0;
921  ft_pix pen_y = 0;
922  size_t i = 0;
923  int lines = 0;
924  ft_pix pen_x_next = 0;
925 
926  /* Space between lines needs to be aligned to the pixel grid (T97310). */
927  ft_pix line_height = FT_PIX_FLOOR(blf_font_height_max_ft_pix(font));
928 
930 
931  struct WordWrapVars {
933  size_t start, last[2];
934  } wrap = {font->wrap_width != -1 ? ft_pix_from_int(font->wrap_width) : INT_MAX, 0, {0, 0}};
935 
936  // printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str);
937  while ((i < str_len) && str[i]) {
938 
939  /* wrap vars */
940  size_t i_curr = i;
941  bool do_draw = false;
942 
943  g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i);
944 
945  if (UNLIKELY(g == NULL)) {
946  continue;
947  }
948  pen_x += blf_kerning(font, g_prev, g);
949 
958  pen_x_next = ft_pix_round_advance(pen_x, g->advance_x);
959  if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
960  do_draw = true;
961  }
962  else if (UNLIKELY(((i < str_len) && str[i]) == 0)) {
963  /* need check here for trailing newline, else we draw it */
964  wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
965  wrap.last[1] = i;
966  do_draw = true;
967  }
968  else if (UNLIKELY(g->c == '\n')) {
969  wrap.last[0] = i_curr + 1;
970  wrap.last[1] = i;
971  do_draw = true;
972  }
973  else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) {
974  wrap.last[0] = i_curr;
975  wrap.last[1] = i_curr;
976  }
977 
978  if (UNLIKELY(do_draw)) {
979  // printf("(%03d..%03d) `%.*s`\n",
980  // wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]);
981 
982  callback(font, gc, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata);
983  wrap.start = wrap.last[0];
984  i = wrap.last[1];
985  pen_x = 0;
986  pen_y -= line_height;
987  g_prev = NULL;
988  lines += 1;
989  continue;
990  }
991 
992  pen_x = pen_x_next;
993  g_prev = g;
994  }
995 
996  // printf("done! lines: %d, width, %d\n", lines, pen_x_next);
997 
998  if (r_info) {
999  r_info->lines = lines;
1000  /* width of last line only (with wrapped lines) */
1001  r_info->width = ft_pix_to_int(pen_x_next);
1002  }
1003 
1005 }
1006 
1007 /* blf_font_draw__wrap */
1009  GlyphCacheBLF *gc,
1010  const char *str,
1011  const size_t str_len,
1012  ft_pix pen_y,
1013  void *UNUSED(userdata))
1014 {
1015  blf_font_draw_ex(font, gc, str, str_len, NULL, pen_y);
1016 }
1018  const char *str,
1019  const size_t str_len,
1020  struct ResultBLF *r_info)
1021 {
1022  blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, NULL);
1023 }
1024 
1025 /* blf_font_boundbox__wrap */
1027  GlyphCacheBLF *gc,
1028  const char *str,
1029  const size_t str_len,
1030  ft_pix pen_y,
1031  void *userdata)
1032 {
1033  rcti *box = userdata;
1034  rcti box_single;
1035 
1036  blf_font_boundbox_ex(font, gc, str, str_len, &box_single, NULL, pen_y);
1037  BLI_rcti_union(box, &box_single);
1038 }
1040  FontBLF *font, const char *str, const size_t str_len, rcti *box, struct ResultBLF *r_info)
1041 {
1042  box->xmin = 32000;
1043  box->xmax = -32000;
1044  box->ymin = 32000;
1045  box->ymax = -32000;
1046 
1047  blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box);
1048 }
1049 
1050 /* blf_font_draw_buffer__wrap */
1052  GlyphCacheBLF *gc,
1053  const char *str,
1054  const size_t str_len,
1055  ft_pix pen_y,
1056  void *UNUSED(userdata))
1057 {
1058  blf_font_draw_buffer_ex(font, gc, str, str_len, NULL, pen_y);
1059 }
1061  const char *str,
1062  const size_t str_len,
1063  struct ResultBLF *r_info)
1064 {
1065  blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
1066 }
1067 
1070 /* -------------------------------------------------------------------- */
1075  const char *str,
1076  const size_t str_len,
1077  int *r_tot_chars)
1078 {
1079  int missing = 0;
1080  size_t i = 0;
1081 
1082  *r_tot_chars = 0;
1083  while (i < str_len) {
1084  unsigned int c;
1085 
1086  if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
1087  i++;
1088  }
1089  else {
1090  c = BLI_str_utf8_as_unicode_step(str, str_len, &i);
1091  if (FT_Get_Char_Index((font)->face, c) == 0) {
1092  missing++;
1093  }
1094  }
1095  (*r_tot_chars)++;
1096  }
1097  return missing;
1098 }
1099 
1102 /* -------------------------------------------------------------------- */
1107 {
1108  ft_pix height_max;
1109  FT_Face face = font->face;
1110  if (FT_IS_SCALABLE(face)) {
1111  height_max = ft_pix_from_int((int)(face->ascender - face->descender) *
1112  (int)face->size->metrics.y_ppem) /
1113  (ft_pix)face->units_per_EM;
1114  }
1115  else {
1116  height_max = (ft_pix)face->size->metrics.height;
1117  }
1118  /* can happen with size 1 fonts */
1119  return MAX2(height_max, ft_pix_from_int(1));
1120 }
1121 
1123 {
1125 }
1126 
1128 {
1129  ft_pix width_max;
1130  const FT_Face face = font->face;
1131  if (FT_IS_SCALABLE(face)) {
1132  width_max = ft_pix_from_int((int)(face->bbox.xMax - face->bbox.xMin) *
1133  (int)face->size->metrics.x_ppem) /
1134  (ft_pix)face->units_per_EM;
1135  }
1136  else {
1137  width_max = (ft_pix)face->size->metrics.max_advance;
1138  }
1139  /* can happen with size 1 fonts */
1140  return MAX2(width_max, ft_pix_from_int(1));
1141 }
1142 
1144 {
1146 }
1147 
1149 {
1150  return ft_pix_to_int((ft_pix)font->face->size->metrics.descender);
1151 }
1152 
1154 {
1155  return ft_pix_to_int((ft_pix)font->face->size->metrics.ascender);
1156 }
1157 
1159 {
1160  if (!font->face->family_name) {
1161  return NULL;
1162  }
1163  return BLI_sprintfN("%s %s", font->face->family_name, font->face->style_name);
1164 }
1165 
1168 /* -------------------------------------------------------------------- */
1172 int blf_font_init(void)
1173 {
1174  memset(&g_batch, 0, sizeof(g_batch));
1177  return FT_Init_FreeType(&ft_lib);
1178 }
1179 
1180 void blf_font_exit(void)
1181 {
1182  FT_Done_FreeType(ft_lib);
1186 }
1187 
1188 void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void))
1189 {
1190  blf_draw_cache_flush = cache_flush_fn;
1191 }
1192 
1195 /* -------------------------------------------------------------------- */
1199 static void blf_font_fill(FontBLF *font)
1200 {
1201  font->aspect[0] = 1.0f;
1202  font->aspect[1] = 1.0f;
1203  font->aspect[2] = 1.0f;
1204  font->pos[0] = 0;
1205  font->pos[1] = 0;
1206  font->angle = 0.0f;
1207 
1208  for (int i = 0; i < 16; i++) {
1209  font->m[i] = 0;
1210  }
1211 
1212  /* annoying bright color so we can see where to add BLF_color calls */
1213  font->color[0] = 255;
1214  font->color[1] = 255;
1215  font->color[2] = 0;
1216  font->color[3] = 255;
1217 
1218  font->clip_rec.xmin = 0;
1219  font->clip_rec.xmax = 0;
1220  font->clip_rec.ymin = 0;
1221  font->clip_rec.ymax = 0;
1222  font->flags = 0;
1223  font->dpi = 0;
1224  font->size = 0;
1225  BLI_listbase_clear(&font->cache);
1226  font->kerning_cache = NULL;
1227 #if BLF_BLUR_ENABLE
1228  font->blur = 0;
1229 #endif
1230  font->tex_size_max = -1;
1231 
1232  font->buf_info.fbuf = NULL;
1233  font->buf_info.cbuf = NULL;
1234  font->buf_info.dims[0] = 0;
1235  font->buf_info.dims[1] = 0;
1236  font->buf_info.ch = 0;
1237  font->buf_info.col_init[0] = 0;
1238  font->buf_info.col_init[1] = 0;
1239  font->buf_info.col_init[2] = 0;
1240  font->buf_info.col_init[3] = 0;
1241 
1242  font->ft_lib = ft_lib;
1243  font->ft_lib_mutex = &ft_lib_mutex;
1245 }
1246 
1247 FontBLF *blf_font_new(const char *name, const char *filepath)
1248 {
1249  FontBLF *font;
1250  FT_Error err;
1251  char *mfile;
1252 
1253  font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
1254  err = FT_New_Face(ft_lib, filepath, 0, &font->face);
1255  if (err) {
1256  if (ELEM(err, FT_Err_Unknown_File_Format, FT_Err_Unimplemented_Feature)) {
1257  printf("Format of this font file is not supported\n");
1258  }
1259  else {
1260  printf("Error encountered while opening font file\n");
1261  }
1262  MEM_freeN(font);
1263  return NULL;
1264  }
1265 
1266  err = FT_Select_Charmap(font->face, FT_ENCODING_UNICODE);
1267  if (err) {
1268  err = FT_Select_Charmap(font->face, FT_ENCODING_APPLE_ROMAN);
1269  }
1270  if (err && font->face->num_charmaps > 0) {
1271  err = FT_Select_Charmap(font->face, font->face->charmaps[0]->encoding);
1272  }
1273  if (err) {
1274  printf("Can't set a character map!\n");
1275  FT_Done_Face(font->face);
1276  MEM_freeN(font);
1277  return NULL;
1278  }
1279 
1280  mfile = blf_dir_metrics_search(filepath);
1281  if (mfile) {
1282  err = FT_Attach_File(font->face, mfile);
1283  if (err) {
1284  fprintf(stderr, "FT_Attach_File failed to load '%s' with error %d\n", filepath, (int)err);
1285  }
1286  MEM_freeN(mfile);
1287  }
1288 
1289  if (FT_HAS_MULTIPLE_MASTERS(font->face)) {
1290  FT_Get_MM_Var(font->face, &(font->variations));
1291  }
1292 
1293  font->name = BLI_strdup(name);
1294  font->filepath = BLI_strdup(filepath);
1295  blf_font_fill(font);
1296 
1297  /* Save TrueType table with bits to quickly test most unicode block coverage. */
1298  TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2);
1299  if (os2_table) {
1300  font->UnicodeRanges[0] = (uint)os2_table->ulUnicodeRange1;
1301  font->UnicodeRanges[1] = (uint)os2_table->ulUnicodeRange2;
1302  font->UnicodeRanges[2] = (uint)os2_table->ulUnicodeRange3;
1303  font->UnicodeRanges[3] = (uint)os2_table->ulUnicodeRange4;
1304  }
1305 
1306  /* Detect "Last resort" fonts. They have everything. Usually except last 5 bits. */
1307  if (font->UnicodeRanges[0] == 0xffffffffU && font->UnicodeRanges[1] == 0xffffffffU &&
1308  font->UnicodeRanges[2] == 0xffffffffU && font->UnicodeRanges[3] >= 0x7FFFFFFU) {
1309  font->flags |= BLF_LAST_RESORT;
1310  }
1311 
1312  if (FT_IS_FIXED_WIDTH(font->face)) {
1313  font->flags |= BLF_MONOSPACED;
1314  }
1315 
1316  if (FT_HAS_KERNING(font->face)) {
1317  /* Create kerning cache table and fill with value indicating "unset". */
1318  font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
1319  for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
1320  for (uint j = 0; j < KERNING_CACHE_TABLE_SIZE; j++) {
1322  }
1323  }
1324  }
1325 
1326  return font;
1327 }
1328 
1329 void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
1330 {
1331  FT_Open_Args open;
1332 
1333  open.flags = FT_OPEN_MEMORY;
1334  open.memory_base = (const FT_Byte *)mem;
1335  open.memory_size = mem_size;
1336  FT_Attach_Stream(font->face, &open);
1337 }
1338 
1339 FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
1340 {
1341  FontBLF *font;
1342  FT_Error err;
1343 
1344  font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new_from_mem");
1345  err = FT_New_Memory_Face(ft_lib, mem, mem_size, 0, &font->face);
1346  if (err) {
1347  MEM_freeN(font);
1348  return NULL;
1349  }
1350 
1351  err = FT_Select_Charmap(font->face, ft_encoding_unicode);
1352  if (err) {
1353  printf("Can't set the unicode character map!\n");
1354  FT_Done_Face(font->face);
1355  MEM_freeN(font);
1356  return NULL;
1357  }
1358 
1359  font->name = BLI_strdup(name);
1360  font->filepath = NULL;
1361  blf_font_fill(font);
1362 
1363  if (FT_HAS_MULTIPLE_MASTERS(font->face)) {
1364  FT_Get_MM_Var(font->face, &(font->variations));
1365  }
1366 
1367  if (FT_HAS_KERNING(font->face)) {
1368  /* Create kerning cache table and fill with value indicating "unset". */
1369  font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
1370  for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
1371  for (uint j = 0; j < KERNING_CACHE_TABLE_SIZE; j++) {
1373  }
1374  }
1375  }
1376 
1377  return font;
1378 }
1379 
1381 {
1382  blf_glyph_cache_clear(font);
1383 
1384  if (font->kerning_cache) {
1385  MEM_freeN(font->kerning_cache);
1386  }
1387 
1388  if (font->variations) {
1389  FT_Done_MM_Var(ft_lib, font->variations);
1390  }
1391 
1392  FT_Done_Face(font->face);
1393  if (font->filepath) {
1394  MEM_freeN(font->filepath);
1395  }
1396  if (font->name) {
1397  MEM_freeN(font->name);
1398  }
1399  MEM_freeN(font);
1400 }
1401 
1404 /* -------------------------------------------------------------------- */
1408 bool blf_font_size(FontBLF *font, float size, unsigned int dpi)
1409 {
1410  /* FreeType uses fixed-point integers in 64ths. */
1411  FT_F26Dot6 ft_size = lroundf(size * 64.0f);
1412  /* Adjust our new size to be on even 64ths. */
1413  size = (float)ft_size / 64.0f;
1414 
1415  if (font->size != size || font->dpi != dpi) {
1416  if (FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi) == FT_Err_Ok) {
1417  font->size = size;
1418  font->dpi = dpi;
1419  }
1420  else {
1421  printf("The current font does not support the size, %f and DPI, %u\n", size, dpi);
1422  return false;
1423  }
1424  }
1425 
1426  return true;
1427 }
1428 
typedef float(TangentPoint)[2]
@ BLF_ROTATION
Definition: BLF_api.h:334
@ BLF_MATRIX
Definition: BLF_api.h:338
@ BLF_LAST_RESORT
Definition: BLF_api.h:353
@ BLF_MONOSPACED
Definition: BLF_api.h:349
@ BLF_WORD_WRAP
Definition: BLF_api.h:340
@ BLF_ASPECT
Definition: BLF_api.h:339
bool(* BLF_GlyphBoundsFn)(const char *str, size_t str_step_ofs, const struct rcti *glyph_step_bounds, int glyph_advance_x, const struct rcti *glyph_bounds, const int glyph_bearing[2], void *user_data)
Definition: BLF_api.h:119
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
void BLI_rcti_union(struct rcti *rct_a, const struct rcti *rct_b)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:899
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t p_len, size_t *__restrict index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
const char * BLI_str_find_prev_char_utf8(const char *p, const char *str_start) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
#define BLI_UTF8_ERR
size_t size_t int BLI_wcwidth(char32_t ucs) ATTR_WARN_UNUSED_RESULT
Definition: string_utf8.c:364
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define GPU_batch_texture_bind(batch, name, tex)
Definition: GPU_batch.h:161
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:287
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:216
void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo)
Definition: gpu_batch.cc:122
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:43
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:223
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:30
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:126
#define GPU_matrix_model_view_get(x)
Definition: GPU_matrix.h:227
#define GPU_matrix_set(x)
Definition: GPU_matrix.h:225
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:119
@ GPU_PRIM_TRI_STRIP
Definition: GPU_primitive.h:24
@ GPU_SHADER_TEXT
Definition: GPU_shader.h:191
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_texture_update_sub(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
Definition: gpu_texture.cc:417
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
int GPU_texture_width(const GPUTexture *tex)
Definition: gpu_texture.cc:602
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:174
void GPU_texture_unbind(GPUTexture *tex)
Definition: gpu_texture.cc:472
#define GPU_vertbuf_create_with_format(format)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
void GPU_vertbuf_use(GPUVertBuf *)
GPUVertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageType)
void GPU_vertbuf_data_len_set(GPUVertBuf *, uint v_len)
void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access)
@ GPU_USAGE_STREAM
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
char * blf_dir_metrics_search(const char *filepath)
Definition: blf_dir.c:135
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data, struct ResultBLF *r_info, ft_pix pen_y)
Definition: blf_font.c:825
float blf_font_height(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:793
BatchBLF g_batch
Definition: blf_font.c:52
size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, const size_t str_len, int width, int *r_width)
Definition: blf_font.c:618
void blf_batch_draw(void)
Definition: blf_font.c:229
static void blf_font_fill(FontBLF *font)
Definition: blf_font.c:1199
int blf_font_ascender(FontBLF *font)
Definition: blf_font.c:1153
static void blf_font_draw_buffer__wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, ft_pix pen_y, void *UNUSED(userdata))
Definition: blf_font.c:1051
static GPUTexture * blf_batch_cache_texture_load(void)
Definition: blf_font.c:189
void blf_font_exit(void)
Definition: blf_font.c:1180
int blf_font_count_missing_chars(FontBLF *font, const char *str, const size_t str_len, int *r_tot_chars)
Definition: blf_font.c:1074
static SpinLock ft_lib_mutex
Definition: blf_font.c:56
static void blf_font_wrap_apply(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info, void(*callback)(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, ft_pix pen_y, void *userdata), void *userdata)
Definition: blf_font.c:907
void blf_font_draw_buffer(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:557
BLI_INLINE GlyphBLF * blf_glyph_from_utf8_and_step(FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p)
Definition: blf_font.c:280
char * blf_display_name(FontBLF *font)
Definition: blf_font.c:1158
void blf_font_free(FontBLF *font)
Definition: blf_font.c:1380
void blf_font_boundbox_foreach_glyph(FontBLF *font, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data, struct ResultBLF *r_info)
Definition: blf_font.c:880
static FT_Library ft_lib
Definition: blf_font.c:55
int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
Definition: blf_font.c:378
FontBLF * blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
Definition: blf_font.c:1339
static void blf_font_draw_buffer_ex(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, struct ResultBLF *r_info, ft_pix pen_y)
Definition: blf_font.c:422
float blf_font_fixed_width(FontBLF *font)
Definition: blf_font.c:817
static void blf_font_boundbox_wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, ft_pix pen_y, void *userdata)
Definition: blf_font.c:1026
static void(* blf_draw_cache_flush)(void)
Definition: blf_font.c:60
static void blf_batch_draw_end(void)
Definition: blf_font.c:262
void blf_font_boundbox__wrap(FontBLF *font, const char *str, const size_t str_len, rcti *box, struct ResultBLF *r_info)
Definition: blf_font.c:1039
static void blf_font_boundbox_ex(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, rcti *box, struct ResultBLF *r_info, ft_pix pen_y)
Definition: blf_font.c:666
void BLF_cache_flush_set_fn(void(*cache_flush_fn)(void))
Definition: blf_font.c:1188
FontBLF * blf_font_new(const char *name, const char *filepath)
Definition: blf_font.c:1247
int blf_font_width_max(FontBLF *font)
Definition: blf_font.c:1143
void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
Definition: blf_font.c:1329
static bool blf_font_width_to_strlen_glyph_process(FontBLF *font, GlyphBLF *g_prev, GlyphBLF *g, ft_pix *pen_x, const int width_i)
Definition: blf_font.c:577
static void blf_batch_draw_exit(void)
Definition: blf_font.c:124
void blf_batch_draw_begin(FontBLF *font)
Definition: blf_font.c:129
bool blf_font_size(FontBLF *font, float size, unsigned int dpi)
Definition: blf_font.c:1408
static ft_pix blf_font_width_max_ft_pix(struct FontBLF *font)
Definition: blf_font.c:1127
static void blf_font_draw__wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, ft_pix pen_y, void *UNUSED(userdata))
Definition: blf_font.c:1008
void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:371
void blf_font_width_and_height(FontBLF *font, const char *str, const size_t str_len, float *r_width, float *r_height, struct ResultBLF *r_info)
Definition: blf_font.c:740
static ft_pix blf_unscaled_F26Dot6_to_pixels(FontBLF *font, FT_Pos value)
Definition: blf_font.c:70
void blf_font_boundbox(FontBLF *font, const char *str, const size_t str_len, rcti *r_box, struct ResultBLF *r_info)
Definition: blf_font.c:732
static SpinLock blf_glyph_cache_mutex
Definition: blf_font.c:57
void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:1060
static void blf_batch_draw_init(void)
Definition: blf_font.c:96
int blf_font_init(void)
Definition: blf_font.c:1172
BLI_INLINE ft_pix blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const GlyphBLF *g)
Definition: blf_font.c:290
float blf_font_width(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:769
void blf_font_draw__wrap(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
Definition: blf_font.c:1017
size_t blf_font_width_to_strlen(FontBLF *font, const char *str, const size_t str_len, int width, int *r_width)
Definition: blf_font.c:590
int blf_font_descender(FontBLF *font)
Definition: blf_font.c:1148
int blf_font_height_max(FontBLF *font)
Definition: blf_font.c:1122
static void blf_font_draw_ex(FontBLF *font, GlyphCacheBLF *gc, const char *str, const size_t str_len, struct ResultBLF *r_info, ft_pix pen_y)
Definition: blf_font.c:331
static ft_pix blf_font_height_max_ft_pix(struct FontBLF *font)
Definition: blf_font.c:1106
void blf_glyph_cache_clear(FontBLF *font)
Definition: blf_glyph.c:151
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x, const int y)
Definition: blf_glyph.c:1108
GlyphBLF * blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
Definition: blf_glyph.c:976
void blf_glyph_cache_release(FontBLF *font)
Definition: blf_glyph.c:129
GlyphCacheBLF * blf_glyph_cache_acquire(FontBLF *font)
Definition: blf_glyph.c:116
#define FT_PIX_FLOOR(x)
BLI_INLINE int ft_pix_to_int_floor(ft_pix v)
#define GLYPH_ASCII_TABLE_SIZE
int32_t ft_pix
BLI_INLINE ft_pix ft_pix_from_int(int v)
#define BLF_BATCH_DRAW_LEN_MAX
#define KERNING_CACHE_TABLE_SIZE
BLI_INLINE ft_pix ft_pix_round_advance(ft_pix v, ft_pix step)
BLI_INLINE int ft_pix_to_int(ft_pix v)
#define KERNING_ENTRY_UNSET
BLI_INLINE int ft_pix_to_int_ceil(ft_pix v)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btMatrix3x3 scaled(const btVector3 &s) const
Create a scaled copy of the matrix.
Definition: btMatrix3x3.h:622
void * user_data
DEGForeachIDComponentCallback callback
SyclQueue void void size_t num_bytes void
#define str(s)
uint col
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
MINLINE void zero_v2_int(int r[2])
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
unsigned int pos_loc
struct GPUBatch * batch
unsigned int col_loc
unsigned int offset_loc
struct GPUVertBuf * verts
struct FontBLF * font
float mat[4][4]
struct GPUVertBufRaw pos_step col_step offset_step glyph_size_step
struct GlyphCacheBLF * glyph_cache
unsigned int glyph_len
unsigned int glyph_size_loc
KerningCacheBLF * kerning_cache
unsigned int dpi
uint UnicodeRanges[4]
SpinLock * glyph_cache_mutex
unsigned char color[4]
FT_MM_Var * variations
float aspect[3]
SpinLock * ft_lib_mutex
FT_Library ft_lib
ListBase cache
FontBufInfoBLF buf_info
float m[16]
unsigned char col_char[4]
unsigned char * cbuf
unsigned int c
GPUTexture * texture
int ascii_table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE]
int lines
Definition: BLF_api.h:369
int width
Definition: BLF_api.h:373
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
int wrap_width(const struct SpaceText *st, struct ARegion *region)
static FT_Error err