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