Blender  V3.3
vfont.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <wctype.h>
13 
14 #include "CLG_log.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "BLI_ghash.h"
19 #include "BLI_listbase.h"
20 #include "BLI_math.h"
21 #include "BLI_math_base_safe.h"
22 #include "BLI_path_util.h"
23 #include "BLI_string.h"
24 #include "BLI_string_utf8.h"
25 #include "BLI_threads.h"
26 #include "BLI_utildefines.h"
27 
28 #include "BLT_translation.h"
29 
30 #include "DNA_curve_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_packedFile_types.h"
33 #include "DNA_vfont_types.h"
34 
35 #include "BKE_anim_path.h"
36 #include "BKE_bpath.h"
37 #include "BKE_curve.h"
38 #include "BKE_global.h"
39 #include "BKE_idtype.h"
40 #include "BKE_lib_id.h"
41 #include "BKE_main.h"
42 #include "BKE_packedFile.h"
43 #include "BKE_vfont.h"
44 #include "BKE_vfontdata.h"
45 
46 #include "BLO_read_write.h"
47 
48 static CLG_LogRef LOG = {"bke.data_transfer"};
50 
51 /**************************** Prototypes **************************/
52 
54 
55 /****************************** VFont Datablock ************************/
56 
57 static void vfont_init_data(ID *id)
58 {
59  VFont *vfont = (VFont *)id;
61 
62  if (pf) {
63  VFontData *vfd;
64 
66  if (vfd) {
67  vfont->data = vfd;
68 
69  BLI_strncpy(vfont->filepath, FO_BUILTIN_NAME, sizeof(vfont->filepath));
70  }
71 
72  /* Free the packed file */
74  }
75 }
76 
77 static void vfont_copy_data(Main *UNUSED(bmain),
78  ID *id_dst,
79  const ID *UNUSED(id_src),
80  const int flag)
81 {
82  VFont *vfont_dst = (VFont *)id_dst;
83 
84  /* We never handle usercount here for own data. */
85  const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
86 
87  /* Just to be sure, should not have any value actually after reading time. */
88  vfont_dst->temp_pf = NULL;
89 
90  if (vfont_dst->packedfile) {
91  vfont_dst->packedfile = BKE_packedfile_duplicate(vfont_dst->packedfile);
92  }
93 
94  if (vfont_dst->data) {
95  vfont_dst->data = BKE_vfontdata_copy(vfont_dst->data, flag_subdata);
96  }
97 }
98 
100 static void vfont_free_data(ID *id)
101 {
102  VFont *vfont = (VFont *)id;
103  BKE_vfont_free_data(vfont);
104 
105  if (vfont->packedfile) {
107  vfont->packedfile = NULL;
108  }
109 }
110 
111 static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
112 {
113  VFont *vfont = (VFont *)id;
114 
115  if (vfont->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
116  return;
117  }
118 
119  if (BKE_vfont_is_builtin(vfont)) {
120  return;
121  }
122 
124 }
125 
126 static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
127 {
128  VFont *vf = (VFont *)id;
129  const bool is_undo = BLO_write_is_undo(writer);
130 
131  /* Clean up, important in undo case to reduce false detection of changed datablocks. */
132  vf->data = NULL;
133  vf->temp_pf = NULL;
134 
135  /* Do not store packed files in case this is a library override ID. */
136  if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) {
137  vf->packedfile = NULL;
138  }
139 
140  /* write LibData */
141  BLO_write_id_struct(writer, VFont, id_address, &vf->id);
142  BKE_id_blend_write(writer, &vf->id);
143 
144  /* direct data */
146 }
147 
148 static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
149 {
150  VFont *vf = (VFont *)id;
151  vf->data = NULL;
152  vf->temp_pf = NULL;
154 }
155 
157  .id_code = ID_VF,
158  .id_filter = FILTER_ID_VF,
159  .main_listbase_index = INDEX_ID_VF,
160  .struct_size = sizeof(VFont),
161  .name = "Font",
162  .name_plural = "fonts",
163  .translation_context = BLT_I18NCONTEXT_ID_VFONT,
165  .asset_type_info = NULL,
166 
168  .copy_data = vfont_copy_data,
169  .free_data = vfont_free_data,
170  .make_local = NULL,
171  .foreach_id = NULL,
172  .foreach_cache = NULL,
173  .foreach_path = vfont_foreach_path,
174  .owner_get = NULL,
175 
176  .blend_write = vfont_blend_write,
177  .blend_read_data = vfont_blend_read_data,
178  .blend_read_lib = NULL,
179  .blend_read_expand = NULL,
180 
181  .blend_read_undo_preserve = NULL,
182 
183  .lib_override_apply_post = NULL,
184 };
185 
186 /***************************** VFont *******************************/
187 
188 void BKE_vfont_free_data(struct VFont *vfont)
189 {
190  if (vfont->data) {
191  if (vfont->data->characters) {
192  GHashIterator gh_iter;
193  GHASH_ITER (gh_iter, vfont->data->characters) {
194  VChar *che = BLI_ghashIterator_getValue(&gh_iter);
195 
196  while (che->nurbsbase.first) {
197  Nurb *nu = che->nurbsbase.first;
198  if (nu->bezt) {
199  MEM_freeN(nu->bezt);
200  }
201  BLI_freelinkN(&che->nurbsbase, nu);
202  }
203 
204  MEM_freeN(che);
205  }
206 
208  }
209 
210  MEM_freeN(vfont->data);
211  vfont->data = NULL;
212  }
213 
214  if (vfont->temp_pf) {
215  BKE_packedfile_free(vfont->temp_pf); /* NULL when the font file can't be found on disk */
216  vfont->temp_pf = NULL;
217  }
218 }
219 
220 static const void *builtin_font_data = NULL;
221 static int builtin_font_size = 0;
222 
223 bool BKE_vfont_is_builtin(const struct VFont *vfont)
224 {
225  return STREQ(vfont->filepath, FO_BUILTIN_NAME);
226 }
227 
228 void BKE_vfont_builtin_register(const void *mem, int size)
229 {
230  builtin_font_data = mem;
232 }
233 
235 {
236  if (!builtin_font_data) {
237  CLOG_ERROR(&LOG, "Internal error, builtin font not loaded");
238 
239  return NULL;
240  }
241 
242  void *mem = MEM_mallocN(builtin_font_size, "vfd_builtin");
243 
244  memcpy(mem, builtin_font_data, builtin_font_size);
245 
247 }
248 
250 {
251  if (vfont == NULL) {
252  return NULL;
253  }
254 
255  /* And then set the data */
256  if (!vfont->data) {
257  PackedFile *pf;
258 
260 
261  if (vfont->data) {
262  /* Check data again, since it might have been already
263  * initialized from other thread (previous check is
264  * not accurate or threading, just prevents unneeded
265  * lock if all the data is here for sure).
266  */
268  return vfont->data;
269  }
270 
271  if (BKE_vfont_is_builtin(vfont)) {
273  }
274  else {
275  if (vfont->packedfile) {
276  pf = vfont->packedfile;
277 
278  /* We need to copy a tmp font to memory unless it is already there */
279  if (vfont->temp_pf == NULL) {
281  }
282  }
283  else {
285 
286  if (vfont->temp_pf == NULL) {
287  vfont->temp_pf = BKE_packedfile_new(
288  NULL, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
289  }
290  }
291  if (!pf) {
292  CLOG_WARN(&LOG, "Font file doesn't exist: %s", vfont->filepath);
293 
294  /* DON'T DO THIS
295  * missing file shouldn't modify path! - campbell */
296 #if 0
297  strcpy(vfont->filepath, FO_BUILTIN_NAME);
298 #endif
300  }
301  }
302 
303  if (pf) {
305  if (pf != vfont->packedfile) {
307  }
308  }
309 
311  }
312 
313  return vfont->data;
314 }
315 
316 VFont *BKE_vfont_load(Main *bmain, const char *filepath)
317 {
318  char filename[FILE_MAXFILE];
319  VFont *vfont = NULL;
320  PackedFile *pf;
321  bool is_builtin;
322 
323  if (STREQ(filepath, FO_BUILTIN_NAME)) {
324  BLI_strncpy(filename, filepath, sizeof(filename));
325 
327  is_builtin = true;
328  }
329  else {
330  BLI_split_file_part(filepath, filename, sizeof(filename));
331  pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
332 
333  is_builtin = false;
334  }
335 
336  if (pf) {
337  VFontData *vfd;
338 
340  if (vfd) {
341  /* If there's a font name, use it for the ID name. */
342  vfont = BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0);
343  vfont->data = vfd;
344  BLI_strncpy(vfont->filepath, filepath, sizeof(vfont->filepath));
345 
346  /* if auto-pack is on store the packed-file in de font structure */
347  if (!is_builtin && (G.fileflags & G_FILE_AUTOPACK)) {
348  vfont->packedfile = pf;
349  }
350 
351  /* Do not add #FO_BUILTIN_NAME to temporary list-base. */
352  if (!STREQ(filename, FO_BUILTIN_NAME)) {
353  vfont->temp_pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
354  }
355  }
356 
357  /* Free the packed file */
358  if (!vfont || vfont->packedfile != pf) {
360  }
361  }
362 
363  return vfont;
364 }
365 
366 VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
367 {
368  VFont *vfont;
369  char str[FILE_MAX], strtest[FILE_MAX];
370 
371  BLI_strncpy(str, filepath, sizeof(str));
373 
374  /* first search an identical filepath */
375  for (vfont = bmain->fonts.first; vfont; vfont = vfont->id.next) {
376  BLI_strncpy(strtest, vfont->filepath, sizeof(vfont->filepath));
377  BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &vfont->id));
378 
379  if (BLI_path_cmp(strtest, str) == 0) {
380  id_us_plus(&vfont->id); /* officially should not, it doesn't link here! */
381  if (r_exists) {
382  *r_exists = true;
383  }
384  return vfont;
385  }
386  }
387 
388  if (r_exists) {
389  *r_exists = false;
390  }
391  return BKE_vfont_load(bmain, filepath);
392 }
393 
394 VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
395 {
396  return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
397 }
398 
399 static VFont *which_vfont(Curve *cu, CharInfo *info)
400 {
401  switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
402  case CU_CHINFO_BOLD:
403  return cu->vfontb ? cu->vfontb : cu->vfont;
404  case CU_CHINFO_ITALIC:
405  return cu->vfonti ? cu->vfonti : cu->vfont;
407  return cu->vfontbi ? cu->vfontbi : cu->vfont;
408  default:
409  return cu->vfont;
410  }
411 }
412 
414 {
415  VFont *vfont;
416 
417  for (vfont = G_MAIN->fonts.first; vfont; vfont = vfont->id.next) {
418  if (BKE_vfont_is_builtin(vfont)) {
419  return vfont;
420  }
421  }
422 
424 }
425 
426 static VChar *find_vfont_char(VFontData *vfd, unsigned int character)
427 {
428  return BLI_ghash_lookup(vfd->characters, POINTER_FROM_UINT(character));
429 }
430 
431 static void build_underline(Curve *cu,
432  ListBase *nubase,
433  const rctf *rect,
434  float yofs,
435  float rot,
436  int charidx,
437  short mat_nr,
438  const float font_size)
439 {
440  Nurb *nu2;
441  BPoint *bp;
442 
443  nu2 = (Nurb *)MEM_callocN(sizeof(Nurb), "underline_nurb");
444  nu2->resolu = cu->resolu;
445  nu2->bezt = NULL;
446  nu2->knotsu = nu2->knotsv = NULL;
447  nu2->charidx = charidx + 1000;
448  if (mat_nr > 0) {
449  nu2->mat_nr = mat_nr - 1;
450  }
451  nu2->pntsu = 4;
452  nu2->pntsv = 1;
453  nu2->orderu = 4;
454  nu2->orderv = 1;
455  nu2->flagu = CU_NURB_CYCLIC;
456 
457  bp = (BPoint *)MEM_calloc_arrayN(4, sizeof(BPoint), "underline_bp");
458 
459  copy_v4_fl4(bp[0].vec, rect->xmin, (rect->ymax + yofs), 0.0f, 1.0f);
460  copy_v4_fl4(bp[1].vec, rect->xmax, (rect->ymax + yofs), 0.0f, 1.0f);
461  copy_v4_fl4(bp[2].vec, rect->xmax, (rect->ymin + yofs), 0.0f, 1.0f);
462  copy_v4_fl4(bp[3].vec, rect->xmin, (rect->ymin + yofs), 0.0f, 1.0f);
463 
464  /* Used by curve extrusion. */
465  bp[0].radius = bp[1].radius = bp[2].radius = bp[3].radius = 1.0f;
466 
467  nu2->bp = bp;
468  BLI_addtail(nubase, nu2);
469 
470  if (rot != 0.0f) {
471  float si = sinf(rot);
472  float co = cosf(rot);
473 
474  for (int i = nu2->pntsu; i > 0; i--) {
475  float *fp = bp->vec;
476 
477  float x = fp[0] - rect->xmin;
478  float y = fp[1] - rect->ymin;
479 
480  fp[0] = (+co * x + si * y) + rect->xmin;
481  fp[1] = (-si * x + co * y) + rect->ymin;
482 
483  bp++;
484  }
485 
486  bp = nu2->bp;
487  }
488 
489  mul_v2_fl(bp[0].vec, font_size);
490  mul_v2_fl(bp[1].vec, font_size);
491  mul_v2_fl(bp[2].vec, font_size);
492  mul_v2_fl(bp[3].vec, font_size);
493 }
494 
496  ListBase *nubase,
497  unsigned int character,
498  CharInfo *info,
499  float ofsx,
500  float ofsy,
501  float rot,
502  int charidx,
503  const float fsize)
504 {
505  VFontData *vfd = vfont_get_data(which_vfont(cu, info));
506  if (!vfd) {
507  return;
508  }
509 
510  /* make a copy at distance ofsx, ofsy with shear */
511  float shear = cu->shear;
512  float si = sinf(rot);
513  float co = cosf(rot);
514 
515  VChar *che = find_vfont_char(vfd, character);
516 
517  /* Select the glyph data */
518  Nurb *nu1 = NULL;
519  if (che) {
520  nu1 = che->nurbsbase.first;
521  }
522 
523  /* Create the character */
524  while (nu1) {
525  BezTriple *bezt1 = nu1->bezt;
526  if (bezt1) {
527  Nurb *nu2 = (Nurb *)MEM_mallocN(sizeof(Nurb), "duplichar_nurb");
528  if (nu2 == NULL) {
529  break;
530  }
531  memcpy(nu2, nu1, sizeof(struct Nurb));
532  nu2->resolu = cu->resolu;
533  nu2->bp = NULL;
534  nu2->knotsu = nu2->knotsv = NULL;
535  nu2->flag = CU_SMOOTH;
536  nu2->charidx = charidx;
537  if (info->mat_nr > 0) {
538  nu2->mat_nr = info->mat_nr - 1;
539  }
540  else {
541  nu2->mat_nr = 0;
542  }
543  /* nu2->trim.first = 0; */
544  /* nu2->trim.last = 0; */
545  int u = nu2->pntsu;
546 
547  BezTriple *bezt2 = (BezTriple *)MEM_malloc_arrayN(u, sizeof(BezTriple), "duplichar_bezt2");
548  if (bezt2 == NULL) {
549  MEM_freeN(nu2);
550  break;
551  }
552  memcpy(bezt2, bezt1, u * sizeof(struct BezTriple));
553  nu2->bezt = bezt2;
554 
555  if (shear != 0.0f) {
556  bezt2 = nu2->bezt;
557 
558  for (int i = nu2->pntsu; i > 0; i--) {
559  bezt2->vec[0][0] += shear * bezt2->vec[0][1];
560  bezt2->vec[1][0] += shear * bezt2->vec[1][1];
561  bezt2->vec[2][0] += shear * bezt2->vec[2][1];
562  bezt2++;
563  }
564  }
565  if (rot != 0.0f) {
566  bezt2 = nu2->bezt;
567  for (int i = nu2->pntsu; i > 0; i--) {
568  float *fp = bezt2->vec[0];
569 
570  float x = fp[0];
571  fp[0] = co * x + si * fp[1];
572  fp[1] = -si * x + co * fp[1];
573  x = fp[3];
574  fp[3] = co * x + si * fp[4];
575  fp[4] = -si * x + co * fp[4];
576  x = fp[6];
577  fp[6] = co * x + si * fp[7];
578  fp[7] = -si * x + co * fp[7];
579 
580  bezt2++;
581  }
582  }
583  bezt2 = nu2->bezt;
584 
585  if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
586  const float sca = cu->smallcaps_scale;
587  for (int i = nu2->pntsu; i > 0; i--) {
588  float *fp = bezt2->vec[0];
589  fp[0] *= sca;
590  fp[1] *= sca;
591  fp[3] *= sca;
592  fp[4] *= sca;
593  fp[6] *= sca;
594  fp[7] *= sca;
595  bezt2++;
596  }
597  }
598  bezt2 = nu2->bezt;
599 
600  for (int i = nu2->pntsu; i > 0; i--) {
601  float *fp = bezt2->vec[0];
602  fp[0] = (fp[0] + ofsx) * fsize;
603  fp[1] = (fp[1] + ofsy) * fsize;
604  fp[3] = (fp[3] + ofsx) * fsize;
605  fp[4] = (fp[4] + ofsy) * fsize;
606  fp[6] = (fp[6] + ofsx) * fsize;
607  fp[7] = (fp[7] + ofsy) * fsize;
608  bezt2++;
609  }
610 
611  BLI_addtail(nubase, nu2);
612  }
613 
614  nu1 = nu1->next;
615  }
616 }
617 
618 int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
619 {
620  Curve *cu = ob->data;
621  EditFont *ef = cu->editfont;
622  int start, end, direction;
623 
624  if ((ob->type != OB_FONT) || (ef == NULL)) {
625  return 0;
626  }
627 
628  BLI_assert(ef->len >= 0);
629  BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1);
630  BLI_assert(ef->selend >= 0 && ef->selend <= ef->len + 1);
631  BLI_assert(ef->pos >= 0 && ef->pos <= ef->len);
632 
633  if (ef->selstart == 0) {
634  return 0;
635  }
636 
637  if (ef->selstart <= ef->selend) {
638  start = ef->selstart - 1;
639  end = ef->selend - 1;
640  direction = 1;
641  }
642  else {
643  start = ef->selend;
644  end = ef->selstart - 2;
645  direction = -1;
646  }
647 
648  if (start == end + 1) {
649  return 0;
650  }
651 
652  BLI_assert(start < end + 1);
653  *r_start = start;
654  *r_end = end;
655  return direction;
656 }
657 
659 {
660  Curve *cu = ob->data;
661  EditFont *ef = cu->editfont;
662 
663  BLI_assert((ob->type == OB_FONT) && ef);
664 
665  CLAMP_MAX(ef->pos, ef->len);
666  CLAMP_MAX(ef->selstart, ef->len + 1);
667  CLAMP_MAX(ef->selend, ef->len);
668 }
669 
670 static float char_width(Curve *cu, VChar *che, CharInfo *info)
671 {
672  /* The character wasn't found, probably ascii = 0, then the width shall be 0 as well */
673  if (che == NULL) {
674  return 0.0f;
675  }
676  if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
677  return che->width * cu->smallcaps_scale;
678  }
679 
680  return che->width;
681 }
682 
683 static void textbox_scale(TextBox *tb_dst, const TextBox *tb_src, float scale)
684 {
685  tb_dst->x = tb_src->x * scale;
686  tb_dst->y = tb_src->y * scale;
687  tb_dst->w = tb_src->w * scale;
688  tb_dst->h = tb_src->h * scale;
689 }
690 
694 struct TempLineInfo {
695  float x_min; /* left margin */
696  float x_max; /* right margin */
697  int char_nr; /* number of characters */
698  int wspace_nr; /* number of white-spaces of line */
699 };
700 
701 /* -------------------------------------------------------------------- */
711 typedef struct VFontToCurveIter {
714  struct {
715  float min;
716  float max;
718  bool ok;
728  bool word_wrap;
729  int status;
731 
732 enum {
737 };
738 
739 #define FONT_TO_CURVE_SCALE_ITERATIONS 20
740 #define FONT_TO_CURVE_SCALE_THRESHOLD 0.0001f
741 
759 static float vfont_ascent(const VFontData *vfd)
760 {
761  return vfd->ascender * vfd->em_height;
762 }
763 static float vfont_descent(const VFontData *vfd)
764 {
765  return vfd->em_height - vfont_ascent(vfd);
766 }
767 
768 static bool vfont_to_curve(Object *ob,
769  Curve *cu,
770  int mode,
771  VFontToCurveIter *iter_data,
772  ListBase *r_nubase,
773  const char32_t **r_text,
774  int *r_text_len,
775  bool *r_text_free,
776  struct CharTrans **r_chartransdata)
777 {
778  EditFont *ef = cu->editfont;
779  EditFontSelBox *selboxes = NULL;
780  VFont *vfont, *oldvfont;
781  VFontData *vfd = NULL;
782  CharInfo *info = NULL, *custrinfo;
783  TextBox tb_scale;
784  bool use_textbox;
785  VChar *che;
786  struct CharTrans *chartransdata = NULL, *ct;
787  struct TempLineInfo *lineinfo;
788  float *f, xof, yof, xtrax, linedist;
789  float twidth = 0, maxlen = 0;
790  int i, slen, j;
791  int curbox;
792  int selstart = 0, selend = 0;
793  int cnr = 0, lnr = 0, wsnr = 0;
794  const char32_t *mem = NULL;
795  char32_t ascii;
796  bool ok = false;
797  const float font_size = cu->fsize * iter_data->scale_to_fit;
798  const bool word_wrap = iter_data->word_wrap;
799  const float xof_scale = safe_divide(cu->xof, font_size);
800  const float yof_scale = safe_divide(cu->yof, font_size);
801  int last_line = -1;
802  /* Length of the text disregarding \n breaks. */
803  float current_line_length = 0.0f;
804  float longest_line_length = 0.0f;
805 
806  /* Text at the beginning of the last used text-box (use for y-axis alignment).
807  * We over-allocate by one to simplify logic of getting last char. */
808  int *i_textbox_array = MEM_callocN(sizeof(*i_textbox_array) * (cu->totbox + 1),
809  "TextBox initial char index");
810 
811 #define MARGIN_X_MIN (xof_scale + tb_scale.x)
812 #define MARGIN_Y_MIN (yof_scale + tb_scale.y)
813 
814  /* NOTE: do calculations including the trailing '\0' of a string
815  * because the cursor can be at that location. */
816 
817  BLI_assert(ob == NULL || ob->type == OB_FONT);
818 
819  /* Set font data */
820  vfont = cu->vfont;
821 
822  if (cu->str == NULL) {
823  return ok;
824  }
825  if (vfont == NULL) {
826  return ok;
827  }
828 
829  vfd = vfont_get_data(vfont);
830 
831  /* The VFont Data can not be found */
832  if (!vfd) {
833  return ok;
834  }
835 
836  if (ef) {
837  slen = ef->len;
838  mem = ef->textbuf;
839  custrinfo = ef->textbufinfo;
840  }
841  else {
842  char32_t *mem_tmp;
843  slen = cu->len_char32;
844 
845  /* Create unicode string */
846  mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem");
847  if (!mem_tmp) {
848  return ok;
849  }
850 
851  BLI_str_utf8_as_utf32(mem_tmp, cu->str, slen + 1);
852 
853  if (cu->strinfo == NULL) { /* old file */
854  cu->strinfo = MEM_calloc_arrayN((slen + 4), sizeof(CharInfo), "strinfo compat");
855  }
856  custrinfo = cu->strinfo;
857  if (!custrinfo) {
858  return ok;
859  }
860 
861  mem = mem_tmp;
862  }
863 
864  if (cu->tb == NULL) {
865  cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBox compat");
866  }
867 
868  if (ef != NULL && ob != NULL) {
869  if (ef->selboxes) {
870  MEM_freeN(ef->selboxes);
871  }
872 
873  if (BKE_vfont_select_get(ob, &selstart, &selend)) {
874  ef->selboxes_len = (selend - selstart) + 1;
875  ef->selboxes = MEM_calloc_arrayN(ef->selboxes_len, sizeof(EditFontSelBox), "font selboxes");
876  }
877  else {
878  ef->selboxes_len = 0;
879  ef->selboxes = NULL;
880  }
881 
882  selboxes = ef->selboxes;
883  }
884 
885  /* calc offset and rotation of each char */
886  ct = chartransdata = MEM_calloc_arrayN((slen + 1), sizeof(struct CharTrans), "buildtext");
887 
888  /* We assume the worst case: 1 character per line (is freed at end anyway) */
889  lineinfo = MEM_malloc_arrayN((slen * 2 + 1), sizeof(*lineinfo), "lineinfo");
890 
891  linedist = cu->linedist;
892 
893  curbox = 0;
894  textbox_scale(&tb_scale, &cu->tb[curbox], safe_divide(1.0f, font_size));
895  use_textbox = (tb_scale.w != 0.0f);
896 
897  xof = MARGIN_X_MIN;
898  yof = MARGIN_Y_MIN;
899 
900  xtrax = 0.5f * cu->spacing - 0.5f;
901 
902  oldvfont = NULL;
903 
904  for (i = 0; i < slen; i++) {
905  custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK | CU_CHINFO_OVERFLOW);
906  }
907 
908  i = 0;
909  while (i <= slen) {
910  /* Characters in the list */
911  info = &custrinfo[i];
912  ascii = mem[i];
913  if (info->flag & CU_CHINFO_SMALLCAPS) {
914  ascii = towupper(ascii);
915  if (mem[i] != ascii) {
917  }
918  }
919 
920  vfont = which_vfont(cu, info);
921 
922  if (vfont == NULL) {
923  break;
924  }
925 
926  if (vfont != oldvfont) {
927  vfd = vfont_get_data(vfont);
928  oldvfont = vfont;
929  }
930 
931  /* VFont Data for VFont couldn't be found */
932  if (!vfd) {
933  MEM_freeN(chartransdata);
934  chartransdata = NULL;
935  MEM_freeN(lineinfo);
936  goto finally;
937  }
938 
939  if (!ELEM(ascii, '\n', '\0')) {
941  che = find_vfont_char(vfd, ascii);
943 
944  /* The character wasn't in the current curve base so load it.
945  * But if the font is built-in then do not try loading since
946  * whole font is in the memory already. */
947  if (che == NULL && BKE_vfont_is_builtin(vfont) == false) {
949  /* Check it once again, char might have been already load
950  * between previous #BLI_rw_mutex_unlock() and this #BLI_rw_mutex_lock().
951  *
952  * Such a check should not be a bottleneck since it wouldn't
953  * happen often once all the chars are load. */
954  if ((che = find_vfont_char(vfd, ascii)) == NULL) {
955  che = BKE_vfontdata_char_from_freetypefont(vfont, ascii);
956  }
958  }
959  }
960  else {
961  che = NULL;
962  }
963 
964  twidth = char_width(cu, che, info);
965 
966  /* Calculate positions. */
967 
968  if ((tb_scale.w != 0.0f) && (ct->dobreak == 0)) { /* May need wrapping. */
969  const float x_available = xof_scale + tb_scale.w;
970  const float x_used = (xof - tb_scale.x) + twidth;
971 
972  if (word_wrap == false) {
973  /* When scale to fit is used, don't do any wrapping.
974  *
975  * Floating precision error can cause the text to be slightly larger.
976  * Assert this is a small value as large values indicate incorrect
977  * calculations with scale-to-fit which shouldn't be ignored. See T89241. */
978  if (x_used > x_available) {
979  BLI_assert_msg(compare_ff_relative(x_used, x_available, FLT_EPSILON, 64),
980  "VFontToCurveIter.scale_to_fit not set correctly!");
981  }
982  }
983  else if (x_used > x_available) {
984  // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
985  bool dobreak = false;
986  for (j = i; (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
987 
988  /* Special case when there are no breaks possible. */
989  if (UNLIKELY(j == 0)) {
990  if (i == slen) {
991  /* Use the behavior of zero a height text-box when a break cannot be inserted.
992  *
993  * Typically when a text-box has any height and overflow is set to scale
994  * the text will wrap to fit the width as necessary. When wrapping isn't
995  * possible it's important to use the same code-path as zero-height lines.
996  * Without this exception a single word will not scale-to-fit (see: T95116). */
997  tb_scale.h = 0.0f;
998  }
999  break;
1000  }
1001 
1002  if (ELEM(mem[j], ' ', '-')) {
1003  ct -= (i - (j - 1));
1004  cnr -= (i - (j - 1));
1005  if (mem[j] == ' ') {
1006  wsnr--;
1007  }
1008  if (mem[j] == '-') {
1009  wsnr++;
1010  }
1011  i = j - 1;
1012  xof = ct->xof;
1013  ct[1].dobreak = 1;
1014  custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
1015  dobreak = true;
1016  break;
1017  }
1018  BLI_assert(chartransdata[j].dobreak == 0);
1019  }
1020 
1021  if (dobreak) {
1022  if (tb_scale.h == 0.0f) {
1023  /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
1024  custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
1025  }
1026  /* Since a break was added, re-run this loop with `i` at it's new value. */
1027  continue;
1028  }
1029  }
1030  }
1031 
1032  if (ascii == '\n' || ascii == 0 || ct->dobreak) {
1033  ct->xof = xof;
1034  ct->yof = yof;
1035  ct->linenr = lnr;
1036  ct->charnr = cnr;
1037 
1038  yof -= linedist;
1039 
1040  lineinfo[lnr].x_min = (xof - xtrax) - tb_scale.x;
1041  lineinfo[lnr].x_max = tb_scale.w;
1042  lineinfo[lnr].char_nr = cnr;
1043  lineinfo[lnr].wspace_nr = wsnr;
1044 
1045  CLAMP_MIN(maxlen, lineinfo[lnr].x_min);
1046 
1047  if ((tb_scale.h != 0.0f) && ((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale)) {
1048  if (cu->totbox > (curbox + 1)) {
1049  maxlen = 0;
1050  curbox++;
1051  i_textbox_array[curbox] = i + 1;
1052 
1053  textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / font_size);
1054 
1055  yof = MARGIN_Y_MIN;
1056  }
1057  else if (last_line == -1) {
1058  last_line = lnr + 1;
1059  info->flag |= CU_CHINFO_OVERFLOW;
1060  }
1061  }
1062 
1063  current_line_length += xof - MARGIN_X_MIN;
1064  if (ct->dobreak) {
1065  current_line_length += twidth;
1066  }
1067  else {
1068  longest_line_length = MAX2(current_line_length, longest_line_length);
1069  current_line_length = 0.0f;
1070  }
1071 
1072  xof = MARGIN_X_MIN;
1073  lnr++;
1074  cnr = 0;
1075  wsnr = 0;
1076  }
1077  else if (ascii == '\t') { /* Tab character. */
1078  float tabfac;
1079 
1080  ct->xof = xof;
1081  ct->yof = yof;
1082  ct->linenr = lnr;
1083  ct->charnr = cnr++;
1084 
1085  tabfac = (xof - MARGIN_X_MIN + 0.01f);
1086  tabfac = 2.0f * ceilf(tabfac / 2.0f);
1087  xof = MARGIN_X_MIN + tabfac;
1088  }
1089  else {
1090  EditFontSelBox *sb = NULL;
1091  float wsfac;
1092 
1093  ct->xof = xof;
1094  ct->yof = yof;
1095  ct->linenr = lnr;
1096  ct->charnr = cnr++;
1097 
1098  if (selboxes && (i >= selstart) && (i <= selend)) {
1099  sb = &selboxes[i - selstart];
1100  sb->y = yof * font_size - linedist * font_size * 0.1f;
1101  sb->h = linedist * font_size;
1102  sb->w = xof * font_size;
1103  }
1104 
1105  if (ascii == ' ') { /* Space character. */
1106  wsfac = cu->wordspace;
1107  wsnr++;
1108  }
1109  else {
1110  wsfac = 1.0f;
1111  }
1112 
1113  /* Set the width of the character. */
1114  twidth = char_width(cu, che, info);
1115 
1116  xof += (twidth * wsfac * (1.0f + (info->kern / 40.0f))) + xtrax;
1117 
1118  if (sb) {
1119  sb->w = (xof * font_size) - sb->w;
1120  }
1121  }
1122  ct++;
1123  i++;
1124  }
1125 
1126  current_line_length += xof + twidth - MARGIN_X_MIN;
1127  longest_line_length = MAX2(current_line_length, longest_line_length);
1128 
1129  cu->lines = 1;
1130  for (i = 0; i <= slen; i++) {
1131  ascii = mem[i];
1132  ct = &chartransdata[i];
1133  if (ascii == '\n' || ct->dobreak) {
1134  cu->lines++;
1135  }
1136  }
1137 
1138  /* Line-data is now: width of line. */
1139 
1140  if (cu->spacemode != CU_ALIGN_X_LEFT) {
1141  ct = chartransdata;
1142 
1143  if (cu->spacemode == CU_ALIGN_X_RIGHT) {
1144  struct TempLineInfo *li;
1145 
1146  for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1147  li->x_min = (li->x_max - li->x_min) + xof_scale;
1148  }
1149 
1150  for (i = 0; i <= slen; i++) {
1151  ct->xof += lineinfo[ct->linenr].x_min;
1152  ct++;
1153  }
1154  }
1155  else if (cu->spacemode == CU_ALIGN_X_MIDDLE) {
1156  struct TempLineInfo *li;
1157 
1158  for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1159  li->x_min = ((li->x_max - li->x_min) + xof_scale) / 2.0f;
1160  }
1161 
1162  for (i = 0; i <= slen; i++) {
1163  ct->xof += lineinfo[ct->linenr].x_min;
1164  ct++;
1165  }
1166  }
1167  else if ((cu->spacemode == CU_ALIGN_X_FLUSH) && use_textbox) {
1168  struct TempLineInfo *li;
1169 
1170  for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1171  li->x_min = ((li->x_max - li->x_min) + xof_scale);
1172 
1173  if (li->char_nr > 1) {
1174  li->x_min /= (float)(li->char_nr - 1);
1175  }
1176  }
1177  for (i = 0; i <= slen; i++) {
1178  for (j = i; (!ELEM(mem[j], '\0', '\n')) && (chartransdata[j].dobreak == 0) && (j < slen);
1179  j++) {
1180  /* do nothing */
1181  }
1182 
1183  // if ((mem[j] != '\n') && (mem[j])) {
1184  ct->xof += ct->charnr * lineinfo[ct->linenr].x_min;
1185  // }
1186  ct++;
1187  }
1188  }
1189  else if ((cu->spacemode == CU_ALIGN_X_JUSTIFY) && use_textbox) {
1190  float curofs = 0.0f;
1191  for (i = 0; i <= slen; i++) {
1192  for (j = i; (mem[j]) && (mem[j] != '\n') && (chartransdata[j].dobreak == 0) && (j < slen);
1193  j++) {
1194  /* pass */
1195  }
1196 
1197  if ((mem[j] != '\n') && ((chartransdata[j].dobreak != 0))) {
1198  if (mem[i] == ' ') {
1199  struct TempLineInfo *li;
1200 
1201  li = &lineinfo[ct->linenr];
1202  curofs += ((li->x_max - li->x_min) + xof_scale) / (float)li->wspace_nr;
1203  }
1204  ct->xof += curofs;
1205  }
1206  if (mem[i] == '\n' || chartransdata[i].dobreak) {
1207  curofs = 0;
1208  }
1209  ct++;
1210  }
1211  }
1212  }
1213 
1214  /* Top-baseline is default, in this case, do nothing. */
1215  if (cu->align_y != CU_ALIGN_Y_TOP_BASELINE) {
1216  if (tb_scale.h != 0.0f) {
1217  /* We need to loop all the text-boxes even the "full" ones.
1218  * This way they all get the same vertical padding. */
1219  for (int tb_index = 0; tb_index < cu->totbox; tb_index++) {
1220  struct CharTrans *ct_first, *ct_last;
1221  const int i_textbox = i_textbox_array[tb_index];
1222  const int i_textbox_next = i_textbox_array[tb_index + 1];
1223  const bool is_last_filled_textbox = ELEM(i_textbox_next, 0, slen + 1);
1224  int lines;
1225 
1226  ct_first = chartransdata + i_textbox;
1227  ct_last = chartransdata + (is_last_filled_textbox ? slen : i_textbox_next - 1);
1228  lines = ct_last->linenr - ct_first->linenr + 1;
1229 
1230  if (cu->overflow == CU_OVERFLOW_TRUNCATE) {
1231  /* Ensure overflow doesn't truncate text, before centering vertically
1232  * giving odd/buggy results, see: T66614. */
1233  if ((tb_index == cu->totbox - 1) && (last_line != -1)) {
1234  lines = last_line - ct_first->linenr;
1235  }
1236  }
1237 
1238  textbox_scale(&tb_scale, &cu->tb[tb_index], 1.0f / font_size);
1239  /* The initial Y origin of the text-box is hard-coded to 1.0f * text scale. */
1240  const float textbox_y_origin = 1.0f;
1241  float yoff = 0.0f;
1242 
1243  switch (cu->align_y) {
1245  break;
1246  case CU_ALIGN_Y_TOP:
1247  yoff = textbox_y_origin - vfont_ascent(vfd);
1248  break;
1249  case CU_ALIGN_Y_CENTER:
1250  yoff = ((((vfd->em_height + (lines - 1) * linedist) * 0.5f) - vfont_ascent(vfd)) -
1251  (tb_scale.h * 0.5f) + textbox_y_origin);
1252  break;
1254  yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.h;
1255  break;
1256  case CU_ALIGN_Y_BOTTOM:
1257  yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.h + vfont_descent(vfd);
1258  break;
1259  }
1260 
1261  for (ct = ct_first; ct <= ct_last; ct++) {
1262  ct->yof += yoff;
1263  }
1264 
1265  if (is_last_filled_textbox) {
1266  break;
1267  }
1268  }
1269  }
1270  else {
1271  /* Non text-box case handled separately. */
1272  float yoff = 0.0f;
1273 
1274  switch (cu->align_y) {
1276  break;
1277  case CU_ALIGN_Y_TOP:
1278  yoff = -vfont_ascent(vfd);
1279  break;
1280  case CU_ALIGN_Y_CENTER:
1281  yoff = ((vfd->em_height + (lnr - 1) * linedist) * 0.5f) - vfont_ascent(vfd);
1282  break;
1284  yoff = (lnr - 1) * linedist;
1285  break;
1286  case CU_ALIGN_Y_BOTTOM:
1287  yoff = (lnr - 1) * linedist + vfont_descent(vfd);
1288  break;
1289  }
1290 
1291  ct = chartransdata;
1292  for (i = 0; i <= slen; i++) {
1293  ct->yof += yoff;
1294  ct++;
1295  }
1296  }
1297  }
1298 
1299  MEM_freeN(lineinfo);
1300  MEM_freeN(i_textbox_array);
1301 
1302  /* TEXT ON CURVE */
1303  /* NOTE: Only #OB_CURVES_LEGACY objects could have a path. */
1304  if (cu->textoncurve && cu->textoncurve->type == OB_CURVES_LEGACY) {
1306  if (cu->textoncurve->runtime.curve_cache != NULL &&
1308  float distfac, imat[4][4], imat3[3][3], cmat[3][3];
1309  float minx, maxx;
1310  float timeofs, sizefac;
1311 
1312  if (ob != NULL) {
1313  invert_m4_m4(imat, ob->obmat);
1314  }
1315  else {
1316  unit_m4(imat);
1317  }
1318  copy_m3_m4(imat3, imat);
1319 
1320  copy_m3_m4(cmat, cu->textoncurve->obmat);
1321  mul_m3_m3m3(cmat, cmat, imat3);
1322  sizefac = normalize_v3(cmat[0]) / font_size;
1323 
1324  ct = chartransdata;
1325  minx = maxx = ct->xof;
1326  ct++;
1327  for (i = 1; i <= slen; i++, ct++) {
1328  if (minx > ct->xof) {
1329  minx = ct->xof;
1330  }
1331  if (maxx < ct->xof) {
1332  maxx = ct->xof;
1333  }
1334  }
1335 
1336  /* We put the x-coordinate exact at the curve, the y is rotated. */
1337 
1338  /* length correction */
1339  const float chartrans_size_x = maxx - minx;
1340  if (chartrans_size_x != 0.0f) {
1341  const CurveCache *cc = cu->textoncurve->runtime.curve_cache;
1342  const float totdist = BKE_anim_path_get_length(cc);
1343  distfac = (sizefac * totdist) / chartrans_size_x;
1344  distfac = (distfac > 1.0f) ? (1.0f / distfac) : 1.0f;
1345  }
1346  else {
1347  /* Happens when there are no characters, set this value to place the text cursor. */
1348  distfac = 0.0f;
1349  }
1350 
1351  timeofs = 0.0f;
1352 
1353  if (distfac < 1.0f) {
1354  /* Path longer than text: space-mode is involved. */
1355 
1356  if (cu->spacemode == CU_ALIGN_X_RIGHT) {
1357  timeofs = 1.0f - distfac;
1358  }
1359  else if (cu->spacemode == CU_ALIGN_X_MIDDLE) {
1360  timeofs = (1.0f - distfac) / 2.0f;
1361  }
1362  else if (cu->spacemode == CU_ALIGN_X_FLUSH) {
1363  distfac = 1.0f;
1364  }
1365  }
1366 
1367  if (chartrans_size_x != 0.0f) {
1368  distfac /= chartrans_size_x;
1369  }
1370 
1371  timeofs += distfac * cu->xof; /* not cyclic */
1372 
1373  ct = chartransdata;
1374  for (i = 0; i <= slen; i++, ct++) {
1375  float ctime, dtime, vec[4], rotvec[3];
1376  float si, co;
1377 
1378  /* Rotate around center character. */
1379  info = &custrinfo[i];
1380  ascii = mem[i];
1381  if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
1382  ascii = towupper(ascii);
1383  }
1384 
1385  che = find_vfont_char(vfd, ascii);
1386 
1387  twidth = char_width(cu, che, info);
1388 
1389  dtime = distfac * 0.5f * twidth;
1390 
1391  ctime = timeofs + distfac * (ct->xof - minx);
1392  CLAMP(ctime, 0.0f, 1.0f);
1393 
1394  /* Calculate the right loc AND the right rot separately. */
1395  /* `vec` needs 4 items. */
1396  BKE_where_on_path(cu->textoncurve, ctime, vec, NULL, NULL, NULL, NULL);
1397  BKE_where_on_path(cu->textoncurve, ctime + dtime, NULL, rotvec, NULL, NULL, NULL);
1398 
1399  mul_v3_fl(vec, sizefac);
1400 
1401  ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]);
1402 
1403  si = sinf(ct->rot);
1404  co = cosf(ct->rot);
1405 
1406  yof = ct->yof;
1407 
1408  ct->xof = vec[0] + si * yof;
1409  ct->yof = vec[1] + co * yof;
1410 
1411  if (selboxes && (i >= selstart) && (i <= selend)) {
1412  EditFontSelBox *sb;
1413  sb = &selboxes[i - selstart];
1414  sb->rot = -ct->rot;
1415  }
1416  }
1417  }
1418  }
1419 
1420  if (selboxes) {
1421  ct = chartransdata;
1422  for (i = 0; i <= selend; i++, ct++) {
1423  if (i >= selstart) {
1424  selboxes[i - selstart].x = ct->xof * font_size;
1425  selboxes[i - selstart].y = ct->yof * font_size;
1426  }
1427  }
1428  }
1429 
1431  iter_data->status == VFONT_TO_CURVE_INIT) {
1432  ct = &chartransdata[ef->pos];
1433 
1434  if (ELEM(mode, FO_CURSUP, FO_PAGEUP) && ct->linenr == 0) {
1435  /* pass */
1436  }
1437  else if (ELEM(mode, FO_CURSDOWN, FO_PAGEDOWN) && ct->linenr == lnr) {
1438  /* pass */
1439  }
1440  else {
1441  switch (mode) {
1442  case FO_CURSUP:
1443  lnr = ct->linenr - 1;
1444  break;
1445  case FO_CURSDOWN:
1446  lnr = ct->linenr + 1;
1447  break;
1448  case FO_PAGEUP:
1449  lnr = ct->linenr - 10;
1450  break;
1451  case FO_PAGEDOWN:
1452  lnr = ct->linenr + 10;
1453  break;
1454  }
1455  cnr = ct->charnr;
1456  /* Seek for char with `lnr` & `cnr`. */
1457  ef->pos = 0;
1458  ct = chartransdata;
1459  for (i = 0; i < slen; i++) {
1460  if (ct->linenr == lnr) {
1461  if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
1462  break;
1463  }
1464  }
1465  else if (ct->linenr > lnr) {
1466  break;
1467  }
1468  ef->pos++;
1469  ct++;
1470  }
1471  }
1472  }
1473 
1474  /* Cursor first. */
1475  if (ef) {
1476  float si, co;
1477 
1478  ct = &chartransdata[ef->pos];
1479  si = sinf(ct->rot);
1480  co = cosf(ct->rot);
1481 
1482  f = ef->textcurs[0];
1483 
1484  f[0] = font_size * (-0.1f * co + ct->xof);
1485  f[1] = font_size * (0.1f * si + ct->yof);
1486 
1487  f[2] = font_size * (0.1f * co + ct->xof);
1488  f[3] = font_size * (-0.1f * si + ct->yof);
1489 
1490  f[4] = font_size * (0.1f * co + 0.8f * si + ct->xof);
1491  f[5] = font_size * (-0.1f * si + 0.8f * co + ct->yof);
1492 
1493  f[6] = font_size * (-0.1f * co + 0.8f * si + ct->xof);
1494  f[7] = font_size * (0.1f * si + 0.8f * co + ct->yof);
1495  }
1496 
1497  if (mode == FO_SELCHANGE) {
1498  MEM_freeN(chartransdata);
1499  chartransdata = NULL;
1500  }
1501  else if (mode == FO_EDIT) {
1502  /* Make NURBS-data. */
1503  BKE_nurbList_free(r_nubase);
1504 
1505  ct = chartransdata;
1506  for (i = 0; i < slen; i++) {
1507  unsigned int cha = (unsigned int)mem[i];
1508  info = &(custrinfo[i]);
1509 
1510  if ((cu->overflow == CU_OVERFLOW_TRUNCATE) && (ob && ob->mode != OB_MODE_EDIT) &&
1511  (info->flag & CU_CHINFO_OVERFLOW)) {
1512  break;
1513  }
1514 
1515  if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
1516  cha = towupper(cha);
1517  }
1518 
1519  /* Only do that check in case we do have an object, otherwise all materials get erased every
1520  * time that code is called without an object. */
1521  if (ob != NULL && (info->mat_nr > (ob->totcol))) {
1522  // CLOG_ERROR(
1523  // &LOG, "Illegal material index (%d) in text object, setting to 0", info->mat_nr);
1524  info->mat_nr = 0;
1525  }
1526  /* We don't want to see any character for '\n'. */
1527  if (cha != '\n') {
1528  BKE_vfont_build_char(cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i, font_size);
1529  }
1530 
1531  if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n')) {
1532  float ulwidth, uloverlap = 0.0f;
1533  rctf rect;
1534 
1535  if ((i < (slen - 1)) && (mem[i + 1] != '\n') &&
1536  ((mem[i + 1] != ' ') || (custrinfo[i + 1].flag & CU_CHINFO_UNDERLINE)) &&
1537  ((custrinfo[i + 1].flag & CU_CHINFO_WRAP) == 0)) {
1538  uloverlap = xtrax + 0.1f;
1539  }
1540  /* Find the character, the characters has to be in the memory already
1541  * since character checking has been done earlier already. */
1542  che = find_vfont_char(vfd, cha);
1543 
1544  twidth = char_width(cu, che, info);
1545  ulwidth = (twidth * (1.0f + (info->kern / 40.0f))) + uloverlap;
1546 
1547  rect.xmin = ct->xof;
1548  rect.xmax = rect.xmin + ulwidth;
1549 
1550  rect.ymin = ct->yof;
1551  rect.ymax = rect.ymin - cu->ulheight;
1552 
1554  cu, r_nubase, &rect, cu->ulpos - 0.05f, ct->rot, i, info->mat_nr, font_size);
1555  }
1556  ct++;
1557  }
1558  }
1559 
1560  if (iter_data->status == VFONT_TO_CURVE_SCALE_ONCE) {
1561  /* That means we were in a final run, just exit. */
1563  iter_data->status = VFONT_TO_CURVE_DONE;
1564  }
1565  else if (cu->overflow == CU_OVERFLOW_NONE) {
1566  /* Do nothing. */
1567  }
1568  else if ((tb_scale.h == 0.0f) && (tb_scale.w == 0.0f)) {
1569  /* Do nothing. */
1570  }
1571  else if (cu->overflow == CU_OVERFLOW_SCALE) {
1572  if ((cu->totbox == 1) && ((tb_scale.w == 0.0f) || (tb_scale.h == 0.0f))) {
1573  /* These are special cases, simpler to deal with. */
1574  if (tb_scale.w == 0.0f) {
1575  /* This is a potential vertical overflow.
1576  * Since there is no width limit, all the new lines are from line breaks. */
1577  if ((last_line != -1) && (lnr > last_line)) {
1578  const float total_text_height = lnr * linedist;
1579  iter_data->scale_to_fit = tb_scale.h / total_text_height;
1580  iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
1581  iter_data->word_wrap = false;
1582  }
1583  }
1584  else if (tb_scale.h == 0.0f) {
1585  /* This is a horizontal overflow. */
1586  if (longest_line_length > tb_scale.w) {
1587  /* We make sure longest line before it broke can fit here. */
1588  float scale_to_fit = tb_scale.w / longest_line_length;
1589 
1590  iter_data->scale_to_fit = scale_to_fit;
1591  iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
1592  iter_data->word_wrap = false;
1593  }
1594  }
1595  }
1596  else {
1597  /* This is the really complicated case, the best we can do is to iterate over
1598  * this function a few times until we get an acceptable result.
1599  *
1600  * Keep in mind that there is no single number that will make all fit to the end.
1601  * In a way, our ultimate goal is to get the highest scale that still leads to the
1602  * number of extra lines to zero. */
1603  if (iter_data->status == VFONT_TO_CURVE_INIT) {
1604  bool valid = true;
1605 
1606  for (int tb_index = 0; tb_index <= curbox; tb_index++) {
1607  TextBox *tb = &cu->tb[tb_index];
1608  if ((tb->w == 0.0f) || (tb->h == 0.0f)) {
1609  valid = false;
1610  break;
1611  }
1612  }
1613 
1614  if (valid && (last_line != -1) && (lnr > last_line)) {
1615  const float total_text_height = lnr * linedist;
1616  float scale_to_fit = tb_scale.h / total_text_height;
1617 
1618  iter_data->bisect.max = 1.0f;
1619  iter_data->bisect.min = scale_to_fit;
1620 
1621  iter_data->status = VFONT_TO_CURVE_BISECT;
1622  }
1623  }
1624  else {
1625  BLI_assert(iter_data->status == VFONT_TO_CURVE_BISECT);
1626  /* Try to get the highest scale that gives us the exactly
1627  * number of lines we need. */
1628  bool valid = false;
1629 
1630  if ((last_line != -1) && (lnr > last_line)) {
1631  /* It is overflowing, scale it down. */
1632  iter_data->bisect.max = iter_data->scale_to_fit;
1633  }
1634  else {
1635  /* It fits inside the text-box, scale it up. */
1636  iter_data->bisect.min = iter_data->scale_to_fit;
1637  valid = true;
1638  }
1639 
1640  /* Bisecting to try to find the best fit. */
1641  iter_data->scale_to_fit = (iter_data->bisect.max + iter_data->bisect.min) * 0.5f;
1642 
1643  /* We iterated enough or got a good enough result. */
1644  if ((!iter_data->iteraction--) || ((iter_data->bisect.max - iter_data->bisect.min) <
1646  if (valid) {
1647  iter_data->status = VFONT_TO_CURVE_DONE;
1648  }
1649  else {
1650  iter_data->scale_to_fit = iter_data->bisect.min;
1651  iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
1652  }
1653  }
1654  }
1655  }
1656  }
1657 
1658  /* Scale to fit only works for single text box layouts. */
1660  /* Always cleanup before going to the scale-to-fit repetition. */
1661  if (r_nubase != NULL) {
1662  BKE_nurbList_free(r_nubase);
1663  }
1664 
1665  if (chartransdata != NULL) {
1666  MEM_freeN(chartransdata);
1667  }
1668 
1669  if (ef == NULL) {
1670  MEM_freeN((void *)mem);
1671  }
1672  return true;
1673  }
1674 
1675  ok = true;
1676 finally:
1677  if (r_text) {
1678  *r_text = mem;
1679  *r_text_len = slen;
1680  *r_text_free = (ef == NULL);
1681  }
1682  else {
1683  if (ef == NULL) {
1684  MEM_freeN((void *)mem);
1685  }
1686  }
1687 
1688  if (chartransdata) {
1689  if (ok && r_chartransdata) {
1690  *r_chartransdata = chartransdata;
1691  }
1692  else {
1693  MEM_freeN(chartransdata);
1694  }
1695  }
1696 
1697  /* Store the effective scale, to use for the text-box lines. */
1698  cu->fsize_realtime = font_size;
1699 
1700  return ok;
1701 
1702 #undef MARGIN_X_MIN
1703 #undef MARGIN_Y_MIN
1704 }
1705 
1706 #undef DESCENT
1707 #undef ASCENT
1708 
1710  Curve *cu,
1711  int mode,
1712  ListBase *r_nubase,
1713  const char32_t **r_text,
1714  int *r_text_len,
1715  bool *r_text_free,
1716  struct CharTrans **r_chartransdata)
1717 {
1719  .iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
1720  .scale_to_fit = 1.0f,
1721  .word_wrap = true,
1722  .ok = true,
1723  .status = VFONT_TO_CURVE_INIT,
1724  };
1725 
1726  do {
1727  data.ok &= vfont_to_curve(
1728  ob, cu, mode, &data, r_nubase, r_text, r_text_len, r_text_free, r_chartransdata);
1729  } while (data.ok && ELEM(data.status, VFONT_TO_CURVE_SCALE_ONCE, VFONT_TO_CURVE_BISECT));
1730 
1731  return data.ok;
1732 }
1733 
1734 #undef FONT_TO_CURVE_SCALE_ITERATIONS
1735 #undef FONT_TO_CURVE_SCALE_THRESHOLD
1736 
1737 bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase)
1738 {
1739  BLI_assert(ob->type == OB_FONT);
1740 
1741  return BKE_vfont_to_curve_ex(ob, ob->data, mode, r_nubase, NULL, NULL, NULL, NULL);
1742 }
1743 
1744 bool BKE_vfont_to_curve(Object *ob, int mode)
1745 {
1746  Curve *cu = ob->data;
1747 
1748  return BKE_vfont_to_curve_ex(ob, ob->data, mode, &cu->nurb, NULL, NULL, NULL, NULL);
1749 }
1750 
1751 /* -------------------------------------------------------------------- */
1755 static struct {
1756  char32_t *text_buffer;
1758  size_t len_utf32;
1759  size_t len_utf8;
1761 
1763 {
1764  MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
1765  MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
1766  g_vfont_clipboard.len_utf32 = 0;
1767  g_vfont_clipboard.len_utf8 = 0;
1768 }
1769 
1770 void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
1771 {
1772  char32_t *text;
1773  CharInfo *info;
1774 
1775  /* Clean previous buffers. */
1777 
1778  text = MEM_malloc_arrayN((len + 1), sizeof(*text), __func__);
1779  if (text == NULL) {
1780  return;
1781  }
1782 
1783  info = MEM_malloc_arrayN(len, sizeof(CharInfo), __func__);
1784  if (info == NULL) {
1785  MEM_freeN(text);
1786  return;
1787  }
1788 
1789  memcpy(text, text_buf, len * sizeof(*text));
1790  text[len] = '\0';
1791  memcpy(info, info_buf, len * sizeof(CharInfo));
1792 
1793  /* store new buffers */
1794  g_vfont_clipboard.text_buffer = text;
1795  g_vfont_clipboard.info_buffer = info;
1797  g_vfont_clipboard.len_utf32 = len;
1798 }
1799 
1800 void BKE_vfont_clipboard_get(char32_t **r_text_buf,
1801  CharInfo **r_info_buf,
1802  size_t *r_len_utf8,
1803  size_t *r_len_utf32)
1804 {
1805  if (r_text_buf) {
1806  *r_text_buf = g_vfont_clipboard.text_buffer;
1807  }
1808 
1809  if (r_info_buf) {
1810  *r_info_buf = g_vfont_clipboard.info_buffer;
1811  }
1812 
1813  if (r_len_utf32) {
1814  *r_len_utf32 = g_vfont_clipboard.len_utf32;
1815  }
1816 
1817  if (r_len_utf8) {
1818  *r_len_utf8 = g_vfont_clipboard.len_utf8;
1819  }
1820 }
1821 
typedef float(TangentPoint)[2]
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
float BKE_anim_path_get_length(const struct CurveCache *curve_cache)
bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path)
Definition: bpath.c:121
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
Definition: BKE_bpath.h:37
void BKE_nurbList_free(struct ListBase *lb)
Definition: curve.cc:649
@ G_FILE_AUTOPACK
Definition: BKE_global.h:209
#define G_MAIN
Definition: BKE_global.h:267
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition: BKE_idtype.h:39
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition: BKE_idtype.h:41
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:126
void * BKE_libblock_alloc(struct Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1050
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
struct PackedFile * BKE_packedfile_new(struct ReportList *reports, const char *filepath, const char *basepath)
Definition: packedFile.c:177
struct PackedFile * BKE_packedfile_new_from_memory(void *mem, int memlen)
Definition: packedFile.c:166
struct PackedFile * BKE_packedfile_duplicate(const struct PackedFile *pf_src)
void BKE_packedfile_blend_write(struct BlendWriter *writer, struct PackedFile *pf)
Definition: packedFile.c:855
void BKE_packedfile_blend_read(struct BlendDataReader *reader, struct PackedFile **pf_p)
Definition: packedFile.c:864
void BKE_packedfile_free(struct PackedFile *pf)
Definition: packedFile.c:140
A structure to represent vector fonts, and to load them from PostScript fonts.
VFontData * BKE_vfontdata_from_freetypefont(struct PackedFile *pf)
VChar * BKE_vfontdata_char_from_freetypefont(struct VFont *vfont, unsigned long character)
VFontData * BKE_vfontdata_copy(const VFontData *vfont_src, int flag)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
#define M_PI
Definition: BLI_math_base.h:20
MINLINE int compare_ff_relative(float a, float b, float max_diff, int max_ulps)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w)
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void mul_v3_fl(float r[3], float f)
#define FILE_MAXFILE
#define FILE_MAX
void BLI_split_file_part(const char *string, char *file, size_t filelen)
Definition: path_util.c:1495
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
#define BLI_path_cmp
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, const char *__restrict src_c, size_t maxncpy) ATTR_NONNULL(1
size_t size_t size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:654
pthread_rwlock_t ThreadRWMutex
Definition: BLI_threads.h:125
#define THREAD_LOCK_READ
Definition: BLI_threads.h:120
#define THREAD_LOCK_WRITE
Definition: BLI_threads.h:121
#define BLI_RWLOCK_INITIALIZER
Definition: BLI_threads.h:123
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition: threads.cc:488
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition: threads.cc:498
#define CLAMP_MAX(a, c)
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_FROM_UINT(i)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1608
#define BLT_I18NCONTEXT_ID_VFONT
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:189
@ INDEX_ID_VF
Definition: DNA_ID.h:1000
#define FILTER_ID_VF
Definition: DNA_ID.h:924
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:561
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_VF
Definition: DNA_ID_enums.h:61
#define MAXTEXTBOX
@ CU_ALIGN_X_FLUSH
@ CU_ALIGN_X_MIDDLE
@ CU_ALIGN_X_LEFT
@ CU_ALIGN_X_JUSTIFY
@ CU_ALIGN_X_RIGHT
@ CU_SMOOTH
@ CU_NURB_CYCLIC
@ CU_ALIGN_Y_TOP
@ CU_ALIGN_Y_BOTTOM_BASELINE
@ CU_ALIGN_Y_CENTER
@ CU_ALIGN_Y_BOTTOM
@ CU_ALIGN_Y_TOP_BASELINE
@ CU_CHINFO_WRAP
@ CU_CHINFO_UNDERLINE
@ CU_CHINFO_BOLD
@ CU_CHINFO_ITALIC
@ CU_CHINFO_SMALLCAPS_CHECK
@ CU_CHINFO_SMALLCAPS
@ CU_CHINFO_OVERFLOW
@ CU_OVERFLOW_SCALE
@ CU_OVERFLOW_TRUNCATE
@ CU_OVERFLOW_NONE
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_FONT
@ OB_CURVES_LEGACY
struct VFont VFont
#define FO_CURSDOWN
#define FO_CURSUP
#define FO_PAGEUP
#define FO_BUILTIN_NAME
#define FO_EDIT
#define FO_PAGEDOWN
#define FO_SELCHANGE
_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
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
int len
Definition: draw_manager.c:108
#define rot(x, k)
#define str(s)
#define pf(_x, _i)
Prefetch 64.
Definition: gim_memory.h:48
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
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
#define G(x, y, z)
#define atan2f(x, y)
Definition: metal/compat.h:227
#define ceilf(x)
Definition: metal/compat.h:225
bool is_builtin(const void *UNUSED(owner), const AttributeIDRef &attribute_id)
T safe_divide(const T &a, const T &b)
eBPathForeachFlag flag
Definition: BKE_bpath.h:78
float vec[4]
float radius
float vec[3][3]
short linenr
Definition: BKE_vfont.h:22
float yof
Definition: BKE_vfont.h:20
float xof
Definition: BKE_vfont.h:20
char dobreak
Definition: BKE_vfont.h:23
const float * anim_path_accum_length
Definition: BKE_curve.h:42
char overflow
float spacing
struct VFont * vfont
float xof
int len_char32
char align_y
struct TextBox * tb
float ulheight
float ulpos
struct EditFont * editfont
short resolu
short lines
float fsize_realtime
char spacemode
float wordspace
struct CharInfo * strinfo
struct VFont * vfontb
struct Object * textoncurve
float shear
char * str
struct VFont * vfonti
float smallcaps_scale
ListBase nurb
float linedist
float fsize
float yof
struct VFont * vfontbi
float textcurs[4][2]
Definition: BKE_vfont.h:36
int selend
Definition: BKE_vfont.h:43
int pos
Definition: BKE_vfont.h:42
EditFontSelBox * selboxes
Definition: BKE_vfont.h:37
int len
Definition: BKE_vfont.h:42
int selboxes_len
Definition: BKE_vfont.h:38
char32_t * textbuf
Definition: BKE_vfont.h:32
int selstart
Definition: BKE_vfont.h:43
struct CharInfo * textbufinfo
Definition: BKE_vfont.h:33
short id_code
Definition: BKE_idtype.h:114
Definition: DNA_ID.h:368
void * next
Definition: DNA_ID.h:369
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase fonts
Definition: BKE_main.h:184
short flagu
short orderu
struct Nurb * next
short orderv
float * knotsu
int charidx
short flag
float * knotsv
BezTriple * bezt
BPoint * bp
short resolu
short mat_nr
struct CurveCache * curve_cache
Object_Runtime runtime
float obmat[4][4]
void * data
int char_nr
Definition: vfont.c:697
int wspace_nr
Definition: vfont.c:698
float x_min
Definition: vfont.c:695
float x_max
Definition: vfont.c:696
float width
Definition: BKE_vfontdata.h:33
ListBase nurbsbase
Definition: BKE_vfontdata.h:31
float ascender
Definition: BKE_vfontdata.h:27
struct GHash * characters
Definition: BKE_vfontdata.h:22
char name[128]
Definition: BKE_vfontdata.h:23
float em_height
Definition: BKE_vfontdata.h:26
float scale_to_fit
Definition: vfont.c:713
struct VFontToCurveIter::@107 bisect
bool word_wrap
Definition: vfont.c:728
int iteraction
Definition: vfont.c:712
struct VFontData * data
char filepath[1024]
struct PackedFile * temp_pf
struct PackedFile * packedfile
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
static PackedFile * get_builtin_packedfile(void)
Definition: vfont.c:234
VFont * BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
Definition: vfont.c:394
static void vfont_init_data(ID *id)
Definition: vfont.c:57
VFont * BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
Definition: vfont.c:366
@ VFONT_TO_CURVE_BISECT
Definition: vfont.c:734
@ VFONT_TO_CURVE_SCALE_ONCE
Definition: vfont.c:735
@ VFONT_TO_CURVE_INIT
Definition: vfont.c:733
@ VFONT_TO_CURVE_DONE
Definition: vfont.c:736
CharInfo * info_buffer
Definition: vfont.c:1757
void BKE_vfont_select_clamp(Object *ob)
Definition: vfont.c:658
static struct @106 g_vfont_clipboard
static float char_width(Curve *cu, VChar *che, CharInfo *info)
Definition: vfont.c:670
static float vfont_descent(const VFontData *vfd)
Definition: vfont.c:763
VFont * BKE_vfont_builtin_get(void)
Definition: vfont.c:413
static int builtin_font_size
Definition: vfont.c:221
bool BKE_vfont_to_curve(Object *ob, int mode)
Definition: vfont.c:1744
void BKE_vfont_free_data(struct VFont *vfont)
Definition: vfont.c:188
void BKE_vfont_build_char(Curve *cu, ListBase *nubase, unsigned int character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx, const float fsize)
Definition: vfont.c:495
static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
Definition: vfont.c:148
static VChar * find_vfont_char(VFontData *vfd, unsigned int character)
Definition: vfont.c:426
static const void * builtin_font_data
Definition: vfont.c:220
int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
Definition: vfont.c:618
static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition: vfont.c:111
static ThreadRWMutex vfont_rwlock
Definition: vfont.c:49
bool BKE_vfont_to_curve_ex(Object *ob, Curve *cu, int mode, ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata)
Definition: vfont.c:1709
static float vfont_ascent(const VFontData *vfd)
Definition: vfont.c:759
static VFont * which_vfont(Curve *cu, CharInfo *info)
Definition: vfont.c:399
char32_t * text_buffer
Definition: vfont.c:1756
static void build_underline(Curve *cu, ListBase *nubase, const rctf *rect, float yofs, float rot, int charidx, short mat_nr, const float font_size)
Definition: vfont.c:431
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
Definition: vfont.c:1770
VFont * BKE_vfont_load(Main *bmain, const char *filepath)
Definition: vfont.c:316
static VFontData * vfont_get_data(VFont *vfont)
Definition: vfont.c:249
bool BKE_vfont_is_builtin(const struct VFont *vfont)
Definition: vfont.c:223
#define FONT_TO_CURVE_SCALE_THRESHOLD
Definition: vfont.c:740
IDTypeInfo IDType_ID_VF
Definition: vfont.c:156
static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: vfont.c:126
void BKE_vfont_builtin_register(const void *mem, int size)
Definition: vfont.c:228
void BKE_vfont_clipboard_get(char32_t **r_text_buf, CharInfo **r_info_buf, size_t *r_len_utf8, size_t *r_len_utf32)
Definition: vfont.c:1800
static bool vfont_to_curve(Object *ob, Curve *cu, int mode, VFontToCurveIter *iter_data, ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata)
Definition: vfont.c:768
struct VFontToCurveIter VFontToCurveIter
bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase)
Definition: vfont.c:1737
#define MARGIN_Y_MIN
#define FONT_TO_CURVE_SCALE_ITERATIONS
Definition: vfont.c:739
size_t len_utf32
Definition: vfont.c:1758
static CLG_LogRef LOG
Definition: vfont.c:48
#define MARGIN_X_MIN
void BKE_vfont_clipboard_free(void)
Definition: vfont.c:1762
static void textbox_scale(TextBox *tb_dst, const TextBox *tb_src, float scale)
Definition: vfont.c:683
static void vfont_free_data(ID *id)
Definition: vfont.c:100
size_t len_utf8
Definition: vfont.c:1759
static void vfont_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *UNUSED(id_src), const int flag)
Definition: vfont.c:77