Merging r40877 through r40911 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / font.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/blenkernel/intern/font.c
31  *  \ingroup bke
32  */
33
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include <stdlib.h>
39 #include <wchar.h>
40 #include <wctype.h>
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_math.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_vfontdata.h"
47 #include "BLI_utildefines.h"
48
49 #include "DNA_packedFile_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_vfont_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_object_types.h"
54
55 #include "BKE_utildefines.h"
56 #include "BKE_packedFile.h"
57 #include "BKE_library.h"
58 #include "BKE_font.h"
59 #include "BKE_global.h"
60 #include "BKE_main.h"
61 #include "BKE_anim.h"
62 #include "BKE_curve.h"
63 #include "BKE_displist.h"
64
65 static ListBase ttfdata= {NULL, NULL};
66
67 /* UTF-8 <-> wchar transformations */
68 size_t chtoutf8(const unsigned long c, char o[4])
69 {
70         // Variables and initialization
71 /*      memset(o, 0, 4);        */
72
73         // Create the utf-8 string
74         if (c < 0x80) {
75                 o[0] = (char) c;
76                 return 1;
77         }
78         else if (c < 0x800) {
79                 o[0] = (0xC0 | (c>>6));
80                 o[1] = (0x80 | (c & 0x3f));
81                 return 2;
82         }
83         else if (c < 0x10000) {
84                 o[0] = (0xe0 | (c >> 12));
85                 o[1] = (0x80 | (c >>6 & 0x3f));
86                 o[2] = (0x80 | (c & 0x3f));
87                 return 3;
88         }
89         else if (c < 0x200000) {
90                 o[0] = (0xf0 | (c>>18));
91                 o[1] = (0x80 | (c >>12 & 0x3f));
92                 o[2] = (0x80 | (c >> 6 & 0x3f));
93                 o[3] = (0x80 | (c & 0x3f));
94                 return 4;
95         }
96
97         /* should we assert here? */
98         return 0;
99 }
100
101 void wcs2utf8s(char *dst, const wchar_t *src)
102 {
103         while(*src) {
104                 dst += chtoutf8(*src++, dst);
105         }
106
107         *dst= '\0';
108 }
109
110 size_t wcsleninu8(wchar_t *src)
111 {
112         char ch_dummy[4];
113         size_t len = 0;
114
115         while(*src) {
116                 len += chtoutf8(*src++, ch_dummy);
117         }
118
119         return len;
120 }
121
122 static size_t utf8slen(const char *strc)
123 {
124         int len=0;
125
126         while(*strc) {
127                 if ((*strc & 0xe0) == 0xc0) {
128                         if((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00)
129                                 strc++;
130                 } else if ((*strc & 0xf0) == 0xe0) {
131                         if((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00)
132                                 strc += 2;
133                 } else if ((*strc & 0xf8) == 0xf0) {
134                         if((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00)
135                                 strc += 3;
136                 }
137
138                 strc++;
139                 len++;
140         }
141
142         return len;
143 }
144
145
146 /* Converts Unicode to wchar
147
148 According to RFC 3629 "UTF-8, a transformation format of ISO 10646"
149 (http://tools.ietf.org/html/rfc3629), the valid UTF-8 encoding are:
150
151   Char. number range  |        UTF-8 octet sequence
152           (hexadecimal)    |              (binary)
153    --------------------+---------------------------------------------
154    0000 0000-0000 007F | 0xxxxxxx
155    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
156    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
157    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
158
159 If the encoding incidated by the first character is incorrect (because the
160 1 to 3 following characters do not match 10xxxxxx), the output is a '?' and
161 only a single input character is consumed.
162
163 */
164
165 size_t utf8towchar(wchar_t *w, const char *c)
166 {
167         int len=0;
168
169         if(w==NULL || c==NULL) return(0);
170
171         while(*c) {
172                 if ((*c & 0xe0) == 0xc0) {
173                         if((c[1] & 0x80) && (c[1] & 0x40) == 0x00) {
174                                 *w=((c[0] &0x1f)<<6) | (c[1]&0x3f);
175                                 c++;
176                         } else {
177                                 *w = '?';
178                         }
179                 } else if ((*c & 0xf0) == 0xe0) {
180                         if((c[1] & c[2] & 0x80) && ((c[1] | c[2]) & 0x40) == 0x00) {
181                                 *w=((c[0] & 0x0f)<<12) | ((c[1]&0x3f)<<6) | (c[2]&0x3f);
182                                 c += 2;
183                         } else {
184                                 *w = '?';
185                         }
186                 } else if ((*c & 0xf8) == 0xf0) {
187                         if((c[1] & c[2] & c[3] & 0x80) && ((c[1] | c[2] | c[3]) & 0x40) == 0x00) {
188                                 *w=((c[0] & 0x07)<<18) | ((c[1]&0x1f)<<12) | ((c[2]&0x3f)<<6) | (c[3]&0x3f);
189                                 c += 3;
190                         } else {
191                                 *w = '?';
192                         }
193                 } else
194                         *w=(c[0] & 0x7f);
195
196                 c++;
197                 w++;
198                 len++;
199         }
200         return len;
201 }
202
203 /* The vfont code */
204 void free_vfont(struct VFont *vf)
205 {
206         if (vf == NULL) return;
207
208         if (vf->data) {
209                 while(vf->data->characters.first)
210                 {
211                         VChar *che = vf->data->characters.first;
212                         
213                         while (che->nurbsbase.first) {
214                                 Nurb *nu = che->nurbsbase.first;
215                                 if (nu->bezt) MEM_freeN(nu->bezt);
216                                 BLI_freelinkN(&che->nurbsbase, nu);
217                         }
218         
219                         BLI_freelinkN(&vf->data->characters, che);
220                 }
221
222                 MEM_freeN(vf->data);
223                 vf->data = NULL;
224         }
225         
226         if (vf->packedfile) {
227                 freePackedFile(vf->packedfile);
228                 vf->packedfile = NULL;
229         }
230 }
231
232 static void *builtin_font_data= NULL;
233 static int builtin_font_size= 0;
234
235 void BKE_font_register_builtin(void *mem, int size)
236 {
237         builtin_font_data= mem;
238         builtin_font_size= size;
239 }
240
241 static PackedFile *get_builtin_packedfile(void)
242 {
243         if (!builtin_font_data) {
244                 printf("Internal error, builtin font not loaded\n");
245
246                 return NULL;
247         } else {
248                 void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
249
250                 memcpy(mem, builtin_font_data, builtin_font_size);
251         
252                 return newPackedFileMemory(mem, builtin_font_size);
253         }
254 }
255
256 void free_ttfont(void)
257 {
258         struct TmpFont *tf;
259
260         for(tf= ttfdata.first; tf; tf= tf->next) {
261                 if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
262                 tf->pf= NULL;
263                 tf->vfont= NULL;
264         }
265         BLI_freelistN(&ttfdata);
266 }
267
268 struct TmpFont *vfont_find_tmpfont(VFont *vfont)
269 {
270         struct TmpFont *tmpfnt = NULL;
271         
272         if(vfont==NULL) return NULL;
273         
274         // Try finding the font from font list
275         tmpfnt = ttfdata.first;
276         while(tmpfnt)
277         {
278                 if(tmpfnt->vfont == vfont)
279                         break;
280                 tmpfnt = tmpfnt->next;
281         }
282         return tmpfnt;
283 }
284
285 static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
286 {
287         struct TmpFont *tmpfnt = NULL;
288         PackedFile *tpf;
289         
290         if(vfont==NULL) return NULL;
291         
292         // Try finding the font from font list
293         tmpfnt = vfont_find_tmpfont(vfont);
294         
295         // And then set the data        
296         if (!vfont->data) {
297                 PackedFile *pf;
298                 
299                 if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) {
300                         pf= get_builtin_packedfile();
301                 } else {
302                         if (vfont->packedfile) {
303                                 pf= vfont->packedfile;
304                                 
305                                 // We need to copy a tmp font to memory unless it is already there
306                                 if(!tmpfnt)
307                                 {
308                                         tpf= MEM_callocN(sizeof(*tpf), "PackedFile");
309                                         tpf->data= MEM_mallocN(pf->size, "packFile");
310                                         tpf->size= pf->size;
311                                         memcpy(tpf->data, pf->data, pf->size);
312                                         
313                                         // Add temporary packed file to globals
314                                         tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
315                                         tmpfnt->pf= tpf;
316                                         tmpfnt->vfont= vfont;
317                                         BLI_addtail(&ttfdata, tmpfnt);
318                                 }
319                         } else {
320                                 pf= newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
321                                 
322                                 if(!tmpfnt)
323                                 {
324                                         tpf= newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
325                                         
326                                         // Add temporary packed file to globals
327                                         tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
328                                         tmpfnt->pf= tpf;
329                                         tmpfnt->vfont= vfont;
330                                         BLI_addtail(&ttfdata, tmpfnt);
331                                 }
332                         }
333                         if(!pf) {
334                                 printf("Font file doesn't exist: %s\n", vfont->name);
335
336                                 strcpy(vfont->name, FO_BUILTIN_NAME);
337                                 pf= get_builtin_packedfile();
338                         }
339                 }
340                 
341                 if (pf) {
342                         vfont->data= BLI_vfontdata_from_freetypefont(pf);
343                         if (pf != vfont->packedfile) {
344                                 freePackedFile(pf);
345                         }
346                 }
347         }
348         
349         return vfont->data;     
350 }
351
352 VFont *load_vfont(Main *bmain, const char *name)
353 {
354         char filename[FILE_MAXFILE];
355         VFont *vfont= NULL;
356         PackedFile *pf;
357         PackedFile *tpf = NULL; 
358         int is_builtin;
359         struct TmpFont *tmpfnt;
360         
361         if (strcmp(name, FO_BUILTIN_NAME)==0) {
362                 BLI_strncpy(filename, name, sizeof(filename));
363                 
364                 pf= get_builtin_packedfile();
365                 is_builtin= 1;
366         } else {
367                 char dir[FILE_MAXDIR];
368                 
369                 BLI_strncpy(dir, name, sizeof(dir));
370                 BLI_splitdirstring(dir, filename);
371
372                 pf= newPackedFile(NULL, name, bmain->name);
373                 tpf= newPackedFile(NULL, name, bmain->name);
374                 
375                 is_builtin= 0;
376         }
377
378         if (pf) {
379                 VFontData *vfd;
380
381                 vfd= BLI_vfontdata_from_freetypefont(pf);
382                 if (vfd) {
383                         vfont = alloc_libblock(&bmain->vfont, ID_VF, filename);
384                         vfont->data = vfd;
385
386                         /* if there's a font name, use it for the ID name */
387                         if (vfd->name[0] != '\0') {
388                                 BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2);
389                         }
390                         BLI_strncpy(vfont->name, name, sizeof(vfont->name));
391
392                         // if autopack is on store the packedfile in de font structure
393                         if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
394                                 vfont->packedfile = pf;
395                         }
396                         
397                         // Do not add FO_BUILTIN_NAME to temporary listbase
398                         if(strcmp(filename, FO_BUILTIN_NAME))
399                         {
400                                 tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
401                                 tmpfnt->pf= tpf;
402                                 tmpfnt->vfont= vfont;
403                                 BLI_addtail(&ttfdata, tmpfnt);
404                         }                       
405                 }
406                 
407                 // Free the packed file
408                 if (!vfont || vfont->packedfile != pf) {
409                         freePackedFile(pf);
410                 }
411         
412                 //XXX waitcursor(0);
413         }
414         
415         return vfont;
416 }
417
418 static VFont *which_vfont(Curve *cu, CharInfo *info)
419 {
420         switch(info->flag & (CU_CHINFO_BOLD|CU_CHINFO_ITALIC)) {
421                 case CU_CHINFO_BOLD:
422                         if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
423                 case CU_CHINFO_ITALIC:
424                         if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
425                 case (CU_CHINFO_BOLD|CU_CHINFO_ITALIC):
426                         if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
427                 default:
428                         return(cu->vfont);
429         }                       
430 }
431
432 VFont *get_builtin_font(void)
433 {
434         VFont *vf;
435         
436         for (vf= G.main->vfont.first; vf; vf= vf->id.next)
437                 if (strcmp(vf->name, FO_BUILTIN_NAME)==0)
438                         return vf;
439         
440         return load_vfont(G.main, FO_BUILTIN_NAME);
441 }
442
443 static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
444 {
445         VChar *che= NULL;
446
447         for(che = vfd->characters.first; che; che = che->next) {
448                 if(che->index == character)
449                         break;
450         }
451         return che; /* NULL if not found */
452 }
453                 
454 static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr)
455 {
456         Nurb *nu2;
457         BPoint *bp;
458         
459         nu2 =(Nurb*) MEM_callocN(sizeof(Nurb),"underline_nurb");
460         if (nu2 == NULL) return;
461         nu2->resolu= cu->resolu;
462         nu2->bezt = NULL;
463         nu2->knotsu = nu2->knotsv = NULL;
464         nu2->flag= CU_2D;
465         nu2->charidx = charidx+1000;
466         if (mat_nr > 0) nu2->mat_nr= mat_nr-1;
467         nu2->pntsu = 4;
468         nu2->pntsv = 1;
469         nu2->orderu = 4;
470         nu2->orderv = 1;
471         nu2->flagu = CU_NURB_CYCLIC;
472
473         bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); 
474         if (bp == NULL){
475                 MEM_freeN(nu2);
476                 return;
477         }
478         nu2->bp = bp;
479
480         nu2->bp[0].vec[0] = x1;
481         nu2->bp[0].vec[1] = y1; 
482         nu2->bp[0].vec[2] = 0;
483         nu2->bp[0].vec[3] = 1.0f;
484         nu2->bp[1].vec[0] = x2;
485         nu2->bp[1].vec[1] = y1;
486         nu2->bp[1].vec[2] = 0;  
487         nu2->bp[1].vec[3] = 1.0f;
488         nu2->bp[2].vec[0] = x2;
489         nu2->bp[2].vec[1] = y2; 
490         nu2->bp[2].vec[2] = 0;
491         nu2->bp[2].vec[3] = 1.0f;
492         nu2->bp[3].vec[0] = x1;
493         nu2->bp[3].vec[1] = y2;
494         nu2->bp[3].vec[2] = 0;  
495         nu2->bp[3].vec[3] = 1.0f;
496         
497         BLI_addtail(&(cu->nurb), nu2);  
498
499 }
500
501 static void buildchar(Main *bmain, Curve *cu, unsigned long character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
502 {
503         BezTriple *bezt1, *bezt2;
504         Nurb *nu1 = NULL, *nu2 = NULL;
505         float *fp, fsize, shear, x, si, co;
506         VFontData *vfd = NULL;
507         VChar *che = NULL;
508         int i;
509
510         vfd= vfont_get_data(bmain, which_vfont(cu, info));
511         if (!vfd) return;
512
513         /*
514         if (cu->selend < cu->selstart) {
515                 if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
516                         sel= 1;
517         }
518         else {
519                 if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
520                         sel= 1;
521         }
522         */
523
524         /* make a copy at distance ofsx,ofsy with shear*/
525         fsize= cu->fsize;
526         shear= cu->shear;
527         si= (float)sin(rot);
528         co= (float)cos(rot);
529
530         che= find_vfont_char(vfd, character);
531         
532         // Select the glyph data
533         if(che)
534                 nu1 = che->nurbsbase.first;
535
536         // Create the character
537         while(nu1)
538         {
539                 bezt1 = nu1->bezt;
540                 if (bezt1){
541                         nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
542                         if (nu2 == NULL) break;
543                         memcpy(nu2, nu1, sizeof(struct Nurb));
544                         nu2->resolu= cu->resolu;
545                         nu2->bp = NULL;
546                         nu2->knotsu = nu2->knotsv = NULL;
547                         nu2->flag= CU_SMOOTH;
548                         nu2->charidx = charidx;
549                         if (info->mat_nr) {
550                                 nu2->mat_nr= info->mat_nr-1;
551                         }
552                         else {
553                                 nu2->mat_nr= 0;
554                         }
555                         /* nu2->trim.first = 0; */
556                         /* nu2->trim.last = 0; */
557                         i = nu2->pntsu;
558
559                         bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2"); 
560                         if (bezt2 == NULL){
561                                 MEM_freeN(nu2);
562                                 break;
563                         }
564                         memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
565                         nu2->bezt = bezt2;
566                         
567                         if (shear != 0.0f) {
568                                 bezt2 = nu2->bezt;
569                                 
570                                 for (i= nu2->pntsu; i > 0; i--) {
571                                         bezt2->vec[0][0] += shear * bezt2->vec[0][1];
572                                         bezt2->vec[1][0] += shear * bezt2->vec[1][1];
573                                         bezt2->vec[2][0] += shear * bezt2->vec[2][1];
574                                         bezt2++;
575                                 }
576                         }
577                         if(rot != 0.0f) {
578                                 bezt2= nu2->bezt;
579                                 for (i=nu2->pntsu; i > 0; i--) {
580                                         fp= bezt2->vec[0];
581                                         
582                                         x= fp[0];
583                                         fp[0]= co*x + si*fp[1];
584                                         fp[1]= -si*x + co*fp[1];
585                                         x= fp[3];
586                                         fp[3]= co*x + si*fp[4];
587                                         fp[4]= -si*x + co*fp[4];
588                                         x= fp[6];
589                                         fp[6]= co*x + si*fp[7];
590                                         fp[7]= -si*x + co*fp[7];
591
592                                         bezt2++;
593                                 }
594                         }
595                         bezt2 = nu2->bezt;
596
597                         if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
598                                 const float sca= cu->smallcaps_scale;
599                                 for (i= nu2->pntsu; i > 0; i--) {
600                                         fp= bezt2->vec[0];
601                                         fp[0] *= sca;
602                                         fp[1] *= sca;
603                                         fp[3] *= sca;
604                                         fp[4] *= sca;
605                                         fp[6] *= sca;
606                                         fp[7] *= sca;
607                                         bezt2++;
608                                 }
609                         }
610                         bezt2 = nu2->bezt;
611
612                         for (i= nu2->pntsu; i > 0; i--) {
613                                 fp= bezt2->vec[0];
614                                 fp[0]= (fp[0]+ofsx)*fsize;
615                                 fp[1]= (fp[1]+ofsy)*fsize;
616                                 fp[3]= (fp[3]+ofsx)*fsize;
617                                 fp[4]= (fp[4]+ofsy)*fsize;
618                                 fp[6]= (fp[6]+ofsx)*fsize;
619                                 fp[7]= (fp[7]+ofsy)*fsize;
620                                 bezt2++;
621                         }
622                         
623                         BLI_addtail(&(cu->nurb), nu2);
624                 }
625                 
626                 nu1 = nu1->next;
627         }
628 }
629
630 int BKE_font_getselection(Object *ob, int *start, int *end)
631 {
632         Curve *cu= ob->data;
633         
634         if (cu->editfont==NULL || ob->type != OB_FONT) return 0;
635
636         if (cu->selstart == 0) return 0;
637         if (cu->selstart <= cu->selend) {
638                 *start = cu->selstart-1;
639                 *end = cu->selend-1;
640                 return 1;
641         }
642         else {
643                 *start = cu->selend;
644                 *end = cu->selstart-2;
645                 return -1;
646         }
647 }
648
649 static float char_width(Curve *cu, VChar *che, CharInfo *info)
650 {
651         // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
652         if(che == NULL) {
653                 return 0.0f;
654         }
655         else if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
656                 return che->width * cu->smallcaps_scale;
657         }
658         else {
659                 return che->width;
660         }
661 }
662
663 struct chartrans *BKE_text_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
664 {
665         VFont *vfont, *oldvfont;
666         VFontData *vfd= NULL;
667         Curve *cu;
668         CharInfo *info = NULL, *custrinfo;
669         TextBox *tb;
670         VChar *che;
671         struct chartrans *chartransdata=NULL, *ct;
672         float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
673         float twidth, maxlen= 0;
674         int i, slen, j;
675         int curbox;
676         int selstart, selend;
677         int utf8len;
678         short cnr=0, lnr=0, wsnr= 0;
679         wchar_t *mem, *tmp, ascii;
680
681         /* renark: do calculations including the trailing '\0' of a string
682            because the cursor can be at that location */
683
684         if(ob->type!=OB_FONT) return NULL;
685
686         // Set font data
687         cu= (Curve *) ob->data;
688         vfont= cu->vfont;
689         
690         if(cu->str == NULL) return NULL;
691         if(vfont == NULL) return NULL;
692
693         // Create unicode string
694         utf8len = utf8slen(cu->str);
695         mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
696         
697         utf8towchar(mem, cu->str);
698
699         // Count the wchar_t string length
700         slen = wcslen(mem);
701
702         if (cu->ulheight == 0.0f)
703                 cu->ulheight = 0.05f;
704         
705         if (cu->strinfo==NULL)  /* old file */
706                 cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat");
707         
708         custrinfo= cu->strinfo;
709         if (cu->editfont)
710                 custrinfo= cu->editfont->textbufinfo;
711         
712         if (cu->tb==NULL)
713                 cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat");
714
715         vfd= vfont_get_data(bmain, vfont);
716
717         /* The VFont Data can not be found */
718         if(!vfd) {
719                 if(mem)
720                         MEM_freeN(mem); 
721                 return NULL;
722         }
723
724         /* calc offset and rotation of each char */
725         ct = chartransdata =
726                 (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
727
728         /* We assume the worst case: 1 character per line (is freed at end anyway) */
729
730         linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
731         linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
732         linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");        
733         linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");                
734         
735         linedist= cu->linedist;
736         
737         xof= cu->xof + (cu->tb[0].x/cu->fsize);
738         yof= cu->yof + (cu->tb[0].y/cu->fsize);
739
740         xtrax= 0.5f*cu->spacing-0.5f;
741
742         oldvfont = NULL;
743
744         for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK);
745
746         if (cu->selboxes) MEM_freeN(cu->selboxes);
747         cu->selboxes = NULL;
748         if (BKE_font_getselection(ob, &selstart, &selend))
749                 cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
750
751         tb = &(cu->tb[0]);
752         curbox= 0;
753         for (i = 0 ; i<=slen ; i++) {
754         makebreak:
755                 // Characters in the list
756                 info = &(custrinfo[i]);
757                 ascii = mem[i];
758                 if(info->flag & CU_CHINFO_SMALLCAPS) {
759                         ascii = towupper(ascii);
760                         if(mem[i] != ascii) {
761                                 mem[i]= ascii;
762                                 info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
763                         }
764                 }
765
766                 vfont = which_vfont(cu, info);
767                 
768                 if(vfont==NULL) break;
769
770                 che= find_vfont_char(vfd, ascii);
771
772                 /*
773                  * The character wasn't in the current curve base so load it
774                  * But if the font is FO_BUILTIN_NAME then do not try loading since
775                  * whole font is in the memory already
776                  */
777                 if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) {
778                         BLI_vfontchar_from_freetypefont(vfont, ascii);
779                 }
780
781                 /* Try getting the character again from the list */
782                 che= find_vfont_char(vfd, ascii);
783
784                 /* No VFont found */
785                 if (vfont==NULL) {
786                         if(mem)
787                                 MEM_freeN(mem);
788                         MEM_freeN(chartransdata);
789                         return NULL;
790                 }
791
792                 if (vfont != oldvfont) {
793                         vfd= vfont_get_data(bmain, vfont);
794                         oldvfont = vfont;
795                 }
796
797                 /* VFont Data for VFont couldn't be found */
798                 if (!vfd) {
799                         if(mem)
800                                 MEM_freeN(mem);
801                         MEM_freeN(chartransdata);
802                         return NULL;
803                 }
804
805                 twidth = char_width(cu, che, info);
806
807                 // Calculate positions
808                 if((tb->w != 0.0f) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) {
809         //              fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
810                         for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
811                                 if (mem[j]==' ' || mem[j]=='-') {
812                                         ct -= (i-(j-1));
813                                         cnr -= (i-(j-1));
814                                         if (mem[j] == ' ') wsnr--;
815                                         if (mem[j] == '-') wsnr++;
816                                         i = j-1;
817                                         xof = ct->xof;
818                                         ct[1].dobreak = 1;
819                                         custrinfo[i+1].flag |= CU_CHINFO_WRAP;
820                                         goto makebreak;
821                                 }
822                                 if (chartransdata[j].dobreak) {
823         //                              fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
824                                         ct->dobreak= 1;
825                                         custrinfo[i+1].flag |= CU_CHINFO_WRAP;
826                                         ct -= 1;
827                                         cnr -= 1;
828                                         i--;
829                                         xof = ct->xof;
830                                         goto makebreak;
831                                 }
832                         }
833                 }
834                 if(ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
835                         ct->xof= xof;
836                         ct->yof= yof;
837                         ct->linenr= lnr;
838                         ct->charnr= cnr;
839                         
840                         yof-= linedist;
841                         
842                         maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize));
843                         linedata[lnr]= xof-tb->x/cu->fsize;
844                         linedata2[lnr]= cnr;
845                         linedata3[lnr]= tb->w/cu->fsize;
846                         linedata4[lnr]= wsnr;
847                         
848                         if ( (tb->h != 0.0f) &&
849                                  ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) &&
850                                  (cu->totbox > (curbox+1)) ) {
851                                 maxlen= 0;
852                                 tb++;
853                                 curbox++;
854                                 yof= cu->yof + tb->y/cu->fsize;
855                         }
856
857                         /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
858 #if 0
859                         if(ascii == '\n' || ascii == '\r')
860                                 xof = cu->xof;
861                         else
862                                 xof= cu->xof + (tb->x/cu->fsize);
863 #else
864                         xof= cu->xof + (tb->x/cu->fsize);
865 #endif
866                         lnr++;
867                         cnr= 0;
868                         wsnr= 0;
869                 }
870                 else if(ascii==9) {     /* TAB */
871                         float tabfac;
872                         
873                         ct->xof= xof;
874                         ct->yof= yof;
875                         ct->linenr= lnr;
876                         ct->charnr= cnr++;
877
878                         tabfac= (xof-cu->xof+0.01f);
879                         tabfac= 2.0f*ceilf(tabfac/2.0f);
880                         xof= cu->xof+tabfac;
881                 }
882                 else {
883                         SelBox *sb= NULL;
884                         float wsfac;
885
886                         ct->xof= xof;
887                         ct->yof= yof;
888                         ct->linenr= lnr;
889                         ct->charnr= cnr++;
890
891                         if (cu->selboxes && (i>=selstart) && (i<=selend)) {
892                                 sb = &(cu->selboxes[i-selstart]);
893                                 sb->y = yof*cu->fsize-linedist*cu->fsize*0.1f;
894                                 sb->h = linedist*cu->fsize;
895                                 sb->w = xof*cu->fsize;
896                         }
897         
898                         if (ascii==32) {
899                                 wsfac = cu->wordspace; 
900                                 wsnr++;
901                         } 
902                         else wsfac = 1.0f;
903                         
904                         // Set the width of the character
905                         twidth = char_width(cu, che, info);
906
907                         xof += (twidth*wsfac*(1.0f+(info->kern/40.0f)) ) + xtrax;
908                         
909                         if (sb) 
910                                 sb->w = (xof*cu->fsize) - sb->w;
911                 }
912                 ct++;
913         }
914         
915         cu->lines= 1;
916         ct= chartransdata;
917         tmp = mem;
918         for (i= 0; i<=slen; i++, tmp++, ct++) {
919                 ascii = *tmp;
920                 if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
921         }       
922
923         // linedata is now: width of line
924         // linedata2 is now: number of characters
925         // linedata3 is now: maxlen of that line
926         // linedata4 is now: number of whitespaces of line
927
928         if(cu->spacemode!=CU_LEFT) {
929                 ct= chartransdata;
930
931                 if(cu->spacemode==CU_RIGHT) {
932                         for(i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i];
933                         for (i=0; i<=slen; i++) {
934                                 ct->xof+= linedata[ct->linenr];
935                                 ct++;
936                         }
937                 } else if(cu->spacemode==CU_MIDDLE) {
938                         for(i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2;
939                         for (i=0; i<=slen; i++) {
940                                 ct->xof+= linedata[ct->linenr];
941                                 ct++;
942                         }
943                 } else if((cu->spacemode==CU_FLUSH) &&
944                                   (cu->tb[0].w != 0.0f)) {
945                         for(i=0;i<lnr;i++)
946                                 if(linedata2[i]>1)
947                                         linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
948                         for (i=0; i<=slen; i++) {
949                                 for (j=i; (mem[j]) && (mem[j]!='\n') && 
950                                                   (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
951 //                              if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
952                                         ct->xof+= ct->charnr*linedata[ct->linenr];
953 //                              }
954                                 ct++;
955                         }
956                 } 
957                 else if((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
958                         float curofs= 0.0f;
959                         for (i=0; i<=slen; i++) {
960                                 for (j=i; (mem[j]) && (mem[j]!='\n') && 
961                                                   (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
962                                 if ((mem[j]!='\r') && (mem[j]!='\n') &&
963                                         ((chartransdata[j].dobreak!=0))) {
964                                         if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
965                                         ct->xof+= curofs;
966                                 }
967                                 if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
968                                 ct++;
969                         }                       
970                 }
971         }
972         
973         /* TEXT ON CURVE */
974         /* Note: Only OB_CURVE objects could have a path  */
975         if(cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
976                 Curve *cucu= cu->textoncurve->data;
977                 int oldflag= cucu->flag;
978                 
979                 cucu->flag |= (CU_PATH+CU_FOLLOW);
980                 
981                 if(cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0);
982                 if(cucu->path) {
983                         float distfac, imat[4][4], imat3[3][3], cmat[3][3];
984                         float minx, maxx, miny, maxy;
985                         float timeofs, sizefac;
986                         
987                         invert_m4_m4(imat, ob->obmat);
988                         copy_m3_m4(imat3, imat);
989
990                         copy_m3_m4(cmat, cu->textoncurve->obmat);
991                         mul_m3_m3m3(cmat, cmat, imat3);
992                         sizefac= normalize_v3(cmat[0])/cu->fsize;
993                         
994                         minx=miny= 1.0e20f;
995                         maxx=maxy= -1.0e20f;
996                         ct= chartransdata;
997                         for (i=0; i<=slen; i++, ct++) {
998                                 if(minx>ct->xof) minx= ct->xof;
999                                 if(maxx<ct->xof) maxx= ct->xof;
1000                                 if(miny>ct->yof) miny= ct->yof;
1001                                 if(maxy<ct->yof) maxy= ct->yof;
1002                         }
1003                         
1004                         /* we put the x-coordinaat exact at the curve, the y is rotated */
1005                         
1006                         /* length correction */
1007                         distfac= sizefac*cucu->path->totdist/(maxx-minx);
1008                         timeofs= 0.0f;
1009                         
1010                         if(distfac > 1.0f) {
1011                                 /* path longer than text: spacemode involves */
1012                                 distfac= 1.0f/distfac;
1013                                 
1014                                 if(cu->spacemode==CU_RIGHT) {
1015                                         timeofs= 1.0f-distfac;
1016                                 }
1017                                 else if(cu->spacemode==CU_MIDDLE) {
1018                                         timeofs= (1.0f-distfac)/2.0f;
1019                                 }
1020                                 else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
1021                                 
1022                         }
1023                         else distfac= 1.0;
1024                         
1025                         distfac/= (maxx-minx);
1026                         
1027                         timeofs+= distfac*cu->xof;      /* not cyclic */
1028                         
1029                         ct= chartransdata;
1030                         for (i=0; i<=slen; i++, ct++) {
1031                                 float ctime, dtime, vec[4], tvec[4], rotvec[3];
1032                                 float si, co;
1033                                 
1034                                 /* rotate around center character */
1035                                 ascii = mem[i];
1036
1037                                 che= find_vfont_char(vfd, ascii);
1038         
1039                                 twidth = char_width(cu, che, info);
1040
1041                                 dtime= distfac*0.5f*twidth;
1042
1043                                 ctime= timeofs + distfac*( ct->xof - minx);
1044                                 CLAMP(ctime, 0.0f, 1.0f);
1045
1046                                 /* calc the right loc AND the right rot separately */
1047                                 /* vec, tvec need 4 items */
1048                                 where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
1049                                 where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL);
1050                                 
1051                                 mul_v3_fl(vec, sizefac);
1052                                 
1053                                 ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
1054
1055                                 si= (float)sin(ct->rot);
1056                                 co= (float)cos(ct->rot);
1057
1058                                 yof= ct->yof;
1059                                 
1060                                 ct->xof= vec[0] + si*yof;
1061                                 ct->yof= vec[1] + co*yof;
1062                                 
1063                         }
1064                         cucu->flag= oldflag;
1065                 }
1066         }
1067
1068         if (cu->selboxes) {
1069                 ct= chartransdata;
1070                 for (i=0; i<=selend; i++, ct++) {
1071                         if (i>=selstart) {
1072                                 cu->selboxes[i-selstart].x = ct->xof*cu->fsize;
1073                                 cu->selboxes[i-selstart].y = ct->yof*cu->fsize;                         
1074                         }
1075                 }
1076         }
1077
1078         if(mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) {
1079                 /* 2: curs up
1080                    3: curs down */
1081                 ct= chartransdata+cu->pos;
1082                 
1083                 if((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0);
1084                 else if((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr);
1085                 else {
1086                         switch(mode) {
1087                                 case FO_CURSUP:         lnr= ct->linenr-1; break;
1088                                 case FO_CURSDOWN:       lnr= ct->linenr+1; break;
1089                                 case FO_PAGEUP:         lnr= ct->linenr-10; break;
1090                                 case FO_PAGEDOWN:       lnr= ct->linenr+10; break;
1091                         }
1092                         cnr= ct->charnr;
1093                         /* seek for char with lnr en cnr */
1094                         cu->pos= 0;
1095                         ct= chartransdata;
1096                         for (i= 0; i<slen; i++) {
1097                                 if(ct->linenr==lnr) {
1098                                         if(ct->charnr==cnr) break;
1099                                         if( (ct+1)->charnr==0) break;
1100                                 }
1101                                 else if(ct->linenr>lnr) break;
1102                                 cu->pos++;
1103                                 ct++;
1104                         }
1105                 }
1106         }
1107         
1108         /* cursor first */
1109         if(cu->editfont) {
1110                 float si, co;
1111                 
1112                 ct= chartransdata+cu->pos;
1113                 si= (float)sin(ct->rot);
1114                 co= (float)cos(ct->rot);
1115                                 
1116                 f= cu->editfont->textcurs[0];
1117                 
1118                 f[0]= cu->fsize*(-0.1f*co + ct->xof);
1119                 f[1]= cu->fsize*(0.1f*si + ct->yof);
1120                 
1121                 f[2]= cu->fsize*(0.1f*co + ct->xof);
1122                 f[3]= cu->fsize*(-0.1f*si + ct->yof);
1123                 
1124                 f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
1125                 f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
1126                 
1127                 f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
1128                 f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
1129                 
1130         }
1131
1132         MEM_freeN(linedata);
1133         MEM_freeN(linedata2);           
1134         MEM_freeN(linedata3);
1135         MEM_freeN(linedata4);
1136
1137         if (mode == FO_SELCHANGE) {
1138                 MEM_freeN(chartransdata);
1139                 MEM_freeN(mem);
1140                 return NULL;
1141         }
1142
1143         if(mode == FO_EDIT) {
1144                 /* make nurbdata */
1145                 freeNurblist(&cu->nurb);
1146                 
1147                 ct= chartransdata;
1148                 if (cu->sepchar==0) {
1149                         for (i= 0; i<slen; i++) {
1150                                 unsigned long cha = (uintptr_t) mem[i];
1151                                 info = &(custrinfo[i]);
1152                                 if (info->mat_nr > (ob->totcol)) {
1153                                         /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
1154                                         info->mat_nr = 0;
1155                                 }
1156                                 // We do not want to see any character for \n or \r
1157                                 if(cha != '\n' && cha != '\r')
1158                                         buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i);
1159                                 
1160                                 if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
1161                                         float ulwidth, uloverlap= 0.0f;
1162                                         
1163                                         if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
1164                                                  ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0)
1165                                                  ) {
1166                                                 uloverlap = xtrax + 0.1f;
1167                                         }
1168                                         // Find the character, the characters has to be in the memory already 
1169                                         // since character checking has been done earlier already.
1170                                         che= find_vfont_char(vfd, cha);
1171
1172                                         twidth = char_width(cu, che, info);
1173                                         ulwidth = cu->fsize * ((twidth* (1.0f+(info->kern/40.0f)))+uloverlap);
1174                                         build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize,
1175                                                                         ct->xof*cu->fsize + ulwidth, 
1176                                                                         ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize - cu->ulheight*cu->fsize,
1177                                                                         i, info->mat_nr);
1178                                 }
1179                                 ct++;
1180                         }
1181                 }
1182                 else {
1183                         int outta = 0;
1184                         for (i= 0; (i<slen) && (outta==0); i++) {
1185                                 ascii = mem[i];
1186                                 info = &(custrinfo[i]);
1187                                 if (cu->sepchar == (i+1)) {
1188                                         float vecyo[3];
1189
1190                                         vecyo[0]= ct->xof;
1191                                         vecyo[1]= ct->yof;
1192                                         vecyo[2]= 0.0f;
1193
1194                                         mem[0] = ascii;
1195                                         mem[1] = 0;
1196                                         custrinfo[0]= *info;
1197                                         cu->pos = 1;
1198                                         cu->len = 1;
1199                                         mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
1200                                         outta = 1;
1201                                         cu->sepchar = 0;
1202                                 }
1203                                 ct++;
1204                         }
1205                 }
1206         }
1207
1208         if(mode==FO_DUPLI) {
1209                 MEM_freeN(mem);
1210                 return chartransdata;
1211         }
1212
1213         if(mem)
1214                 MEM_freeN(mem);
1215
1216         MEM_freeN(chartransdata);
1217         return NULL;
1218 }