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