6 * ***** BEGIN GPL LICENSE BLOCK *****
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 * All rights reserved.
25 * The Original Code is: all of this file.
27 * Contributor(s): none yet.
29 * ***** END GPL LICENSE BLOCK *****
42 #include "MEM_guardedalloc.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_vfontdata.h"
48 #include "DNA_packedFile_types.h"
49 #include "DNA_curve_types.h"
50 #include "DNA_vfont_types.h"
51 #include "DNA_scene_types.h"
53 #include "BKE_utildefines.h"
55 #include "BKE_packedFile.h"
57 #include "BKE_library.h"
59 #include "BKE_global.h"
62 #include "BKE_curve.h"
63 #include "BKE_displist.h"
65 static ListBase ttfdata= {NULL, NULL};
67 /* UTF-8 <-> wchar transformations */
69 chtoutf8(unsigned long c, char *o)
71 // Variables and initialization
72 /* memset(o, 0, 16); */
74 // Create the utf-8 string
81 o[0] = (0xC0 | (c>>6));
82 o[1] = (0x80 | (c & 0x3f));
86 o[0] = (0xe0 | (c >> 12));
87 o[1] = (0x80 | (c >>6 & 0x3f));
88 o[2] = (0x80 | (c & 0x3f));
90 else if (c < 0x200000)
92 o[0] = (0xf0 | (c>>18));
93 o[1] = (0x80 | (c >>12 & 0x3f));
94 o[2] = (0x80 | (c >> 6 & 0x3f));
95 o[3] = (0x80 | (c & 0x3f));
100 wcs2utf8s(char *dst, wchar_t *src)
107 chtoutf8(*src++, ch);
113 wcsleninu8(wchar_t *src)
121 chtoutf8(*src++, ch);
122 len = len + strlen(ch);
129 static utf8slen(char *src)
131 int size = 0, index = 0;
141 else if((c & 0xe0) == 0xe0)
157 /* Converts Unicode to wchar
159 According to RFC 3629 "UTF-8, a transformation format of ISO 10646"
160 (http://tools.ietf.org/html/rfc3629), the valid UTF-8 encoding are:
162 Char. number range | UTF-8 octet sequence
163 (hexadecimal) | (binary)
164 --------------------+---------------------------------------------
165 0000 0000-0000 007F | 0xxxxxxx
166 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
167 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
168 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
170 If the encoding incidated by the first character is incorrect (because the
171 1 to 3 following characters do not match 10xxxxxx), the output is a '?' and
172 only a single input character is consumed.
176 int utf8towchar(wchar_t *w, char *c)
180 if(w==NULL || c==NULL) return(0);
183 if ((*c & 0xe0) == 0xc0) {
184 if((c[1] & 0x80) && (c[1] & 0x40) == 0x00) {
185 *w=((c[0] &0x1f)<<6) | (c[1]&0x3f);
190 } else if ((*c & 0xf0) == 0xe0) {
191 if((c[1] & c[2] & 0x80) && ((c[1] | c[2]) & 0x40) == 0x00) {
192 *w=((c[0] & 0x0f)<<12) | ((c[1]&0x3f)<<6) | (c[2]&0x3f);
197 } else if ((*c & 0xf8) == 0xf0) {
198 if((c[1] & c[2] & c[3] & 0x80) && ((c[1] | c[2] | c[3]) & 0x40) == 0x00) {
199 *w=((c[0] & 0x07)<<18) | ((c[1]&0x1f)<<12) | ((c[2]&0x3f)<<6) | (c[3]&0x3f);
215 void free_vfont(struct VFont *vf)
220 while(vf->data->characters.first)
222 VChar *che = vf->data->characters.first;
224 while (che->nurbsbase.first) {
225 Nurb *nu = che->nurbsbase.first;
226 if (nu->bezt) MEM_freeN(nu->bezt);
227 BLI_freelinkN(&che->nurbsbase, nu);
230 BLI_freelinkN(&vf->data->characters, che);
237 if (vf->packedfile) {
238 freePackedFile(vf->packedfile);
239 vf->packedfile = NULL;
243 static void *builtin_font_data= NULL;
244 static int builtin_font_size= 0;
246 void BKE_font_register_builtin(void *mem, int size)
248 builtin_font_data= mem;
249 builtin_font_size= size;
252 static PackedFile *get_builtin_packedfile(void)
254 if (!builtin_font_data) {
255 printf("Internal error, builtin font not loaded\n");
259 void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
261 memcpy(mem, builtin_font_data, builtin_font_size);
263 return newPackedFileMemory(mem, builtin_font_size);
267 void free_ttfont(void)
273 freePackedFile(tf->pf);
278 BLI_freelistN(&ttfdata);
281 struct TmpFont *vfont_find_tmpfont(VFont *vfont)
283 struct TmpFont *tmpfnt = NULL;
285 if(vfont==NULL) return NULL;
287 // Try finding the font from font list
288 tmpfnt = ttfdata.first;
291 if(tmpfnt->vfont == vfont)
293 tmpfnt = tmpfnt->next;
298 static VFontData *vfont_get_data(VFont *vfont)
300 struct TmpFont *tmpfnt = NULL;
303 if(vfont==NULL) return NULL;
305 // Try finding the font from font list
306 tmpfnt = vfont_find_tmpfont(vfont);
308 // And then set the data
312 if (BLI_streq(vfont->name, "<builtin>")) {
313 pf= get_builtin_packedfile();
315 if (vfont->packedfile) {
316 pf= vfont->packedfile;
318 // We need to copy a tmp font to memory unless it is already there
321 tpf= MEM_callocN(sizeof(*tpf), "PackedFile");
322 tpf->data= MEM_mallocN(pf->size, "packFile");
324 memcpy(tpf->data, pf->data, pf->size);
326 // Add temporary packed file to globals
327 tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
329 tmpfnt->vfont= vfont;
330 BLI_addtail(&ttfdata, tmpfnt);
333 pf= newPackedFile(NULL, vfont->name);
337 tpf= newPackedFile(NULL, vfont->name);
339 // Add temporary packed file to globals
340 tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
342 tmpfnt->vfont= vfont;
343 BLI_addtail(&ttfdata, tmpfnt);
347 printf("Font file doesn't exist: %s\n", vfont->name);
349 strcpy(vfont->name, "<builtin>");
350 pf= get_builtin_packedfile();
355 vfont->data= BLI_vfontdata_from_freetypefont(pf);
356 if (pf != vfont->packedfile) {
365 VFont *load_vfont(char *name)
367 char filename[FILE_MAXFILE];
370 PackedFile *tpf = NULL;
372 struct TmpFont *tmpfnt;
374 if (BLI_streq(name, "<builtin>")) {
375 strcpy(filename, name);
377 pf= get_builtin_packedfile();
380 char dir[FILE_MAXDIR];
383 BLI_splitdirstring(dir, filename);
385 pf= newPackedFile(NULL, name);
386 tpf= newPackedFile(NULL, name);
394 vfd= BLI_vfontdata_from_freetypefont(pf);
396 vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
399 /* if there's a font name, use it for the ID name */
400 if (strcmp(vfd->name, "")!=0) {
401 BLI_strncpy(vfont->id.name+2, vfd->name, 21);
403 BLI_strncpy(vfont->name, name, sizeof(vfont->name));
405 // if autopack is on store the packedfile in de font structure
406 if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
407 vfont->packedfile = pf;
410 // Do not add <builtin> to temporary listbase
411 if(strcmp(filename, "<builtin>"))
413 tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
415 tmpfnt->vfont= vfont;
416 BLI_addtail(&ttfdata, tmpfnt);
420 // Free the packed file
421 if (!vfont || vfont->packedfile != pf) {
431 static VFont *which_vfont(Curve *cu, CharInfo *info)
433 switch(info->flag & CU_STYLE) {
435 if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
437 if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
438 case (CU_BOLD|CU_ITALIC):
439 if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
445 VFont *get_builtin_font(void)
449 for (vf= G.main->vfont.first; vf; vf= vf->id.next)
450 if (BLI_streq(vf->name, "<builtin>"))
453 return load_vfont("<builtin>");
456 static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr)
461 nu2 =(Nurb*) MEM_callocN(sizeof(Nurb),"underline_nurb");
462 if (nu2 == NULL) return;
463 nu2->resolu= cu->resolu;
465 nu2->knotsu = nu2->knotsv = NULL;
467 nu2->charidx = charidx+1000;
468 if (mat_nr > 0) nu2->mat_nr= mat_nr-1;
473 nu2->flagu = CU_NURB_CYCLIC;
475 bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp");
482 nu2->bp[0].vec[0] = x1;
483 nu2->bp[0].vec[1] = y1;
484 nu2->bp[0].vec[2] = 0;
485 nu2->bp[0].vec[3] = 1.0;
486 nu2->bp[1].vec[0] = x2;
487 nu2->bp[1].vec[1] = y1;
488 nu2->bp[1].vec[2] = 0;
489 nu2->bp[1].vec[3] = 1.0;
490 nu2->bp[2].vec[0] = x2;
491 nu2->bp[2].vec[1] = y2;
492 nu2->bp[2].vec[2] = 0;
493 nu2->bp[2].vec[3] = 1.0;
494 nu2->bp[3].vec[0] = x1;
495 nu2->bp[3].vec[1] = y2;
496 nu2->bp[3].vec[2] = 0;
497 nu2->bp[3].vec[3] = 1.0;
499 BLI_addtail(&(cu->nurb), nu2);
503 static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
505 BezTriple *bezt1, *bezt2;
506 Nurb *nu1 = NULL, *nu2 = NULL;
507 float *fp, fsize, shear, x, si, co;
508 VFontData *vfd = NULL;
512 vfd= vfont_get_data(which_vfont(cu, info));
515 if (cu->selend < cu->selstart) {
516 if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
520 if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
524 /* make a copy at distance ofsx,ofsy with shear*/
530 // Find the correct character from the font
531 che = vfd->characters.first;
534 if(che->index == character)
539 // Select the glyph data
541 nu1 = che->nurbsbase.first;
543 // Create the character
548 nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
550 memcpy(nu2, nu1, sizeof(struct Nurb));
551 nu2->resolu= cu->resolu;
553 nu2->knotsu = nu2->knotsv = NULL;
554 nu2->flag= CU_SMOOTH;
555 nu2->charidx = charidx;
557 nu2->mat_nr= info->mat_nr-1;
562 /* nu2->trim.first = 0; */
563 /* nu2->trim.last = 0; */
566 bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2");
571 memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
577 for (i= nu2->pntsu; i > 0; i--) {
578 bezt2->vec[0][0] += shear * bezt2->vec[0][1];
579 bezt2->vec[1][0] += shear * bezt2->vec[1][1];
580 bezt2->vec[2][0] += shear * bezt2->vec[2][1];
586 for (i=nu2->pntsu; i > 0; i--) {
590 fp[0]= co*x + si*fp[1];
591 fp[1]= -si*x + co*fp[1];
593 fp[3]= co*x + si*fp[4];
594 fp[4]= -si*x + co*fp[4];
596 fp[6]= co*x + si*fp[7];
597 fp[7]= -si*x + co*fp[7];
604 for (i= nu2->pntsu; i > 0; i--) {
607 fp[0]= (fp[0]+ofsx)*fsize;
608 fp[1]= (fp[1]+ofsy)*fsize;
609 fp[3]= (fp[3]+ofsx)*fsize;
610 fp[4]= (fp[4]+ofsy)*fsize;
611 fp[6]= (fp[6]+ofsx)*fsize;
612 fp[7]= (fp[7]+ofsy)*fsize;
616 BLI_addtail(&(cu->nurb), nu2);
623 int BKE_font_getselection(Object *ob, int *start, int *end)
627 if (cu->editfont==NULL || ob->type != OB_FONT) return 0;
629 if (cu->selstart == 0) return 0;
630 if (cu->selstart <= cu->selend) {
631 *start = cu->selstart-1;
637 *end = cu->selstart-2;
642 struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
644 VFont *vfont, *oldvfont;
645 VFontData *vfd= NULL;
647 CharInfo *info, *custrinfo;
650 struct chartrans *chartransdata=NULL, *ct;
651 float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
652 float twidth, maxlen= 0;
655 int selstart, selend;
657 short cnr=0, lnr=0, wsnr= 0;
658 wchar_t *mem, *tmp, ascii;
660 /* renark: do calculations including the trailing '\0' of a string
661 because the cursor can be at that location */
663 if(ob->type!=OB_FONT) return 0;
666 cu= (Curve *) ob->data;
669 if(cu->str == NULL) return 0;
670 if(vfont == NULL) return 0;
672 // Create unicode string
673 utf8len = utf8slen(cu->str);
674 tmp = mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
676 utf8towchar(mem, cu->str);
678 // Count the wchar_t string length
681 if (cu->ulheight == 0.0)
684 if (cu->strinfo==NULL) /* old file */
685 cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat");
687 custrinfo= cu->strinfo;
689 custrinfo= cu->editfont->textbufinfo;
692 cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat");
694 vfd= vfont_get_data(vfont);
696 /* The VFont Data can not be found */
703 /* calc offset and rotation of each char */
705 (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
707 /* We assume the worst case: 1 character per line (is freed at end anyway) */
709 linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
710 linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
711 linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");
712 linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");
714 linedist= cu->linedist;
716 xof= cu->xof + (cu->tb[0].x/cu->fsize);
717 yof= cu->yof + (cu->tb[0].y/cu->fsize);
719 xtrax= 0.5f*cu->spacing-0.5f;
723 for (i=0; i<slen; i++) custrinfo[i].flag &= ~CU_WRAP;
725 if (cu->selboxes) MEM_freeN(cu->selboxes);
727 if (BKE_font_getselection(ob, &selstart, &selend))
728 cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
732 for (i = 0 ; i<=slen ; i++) {
734 // Characters in the list
735 che = vfd->characters.first;
737 info = &(custrinfo[i]);
738 vfont = which_vfont(cu, info);
740 if(vfont==NULL) break;
742 // Find the character
744 if(che->index == ascii)
750 * The character wasn't in the current curve base so load it
751 * But if the font is <builtin> then do not try loading since
752 * whole font is in the memory already
754 if(che == NULL && strcmp(vfont->name, "<builtin>")) {
755 BLI_vfontchar_from_freetypefont(vfont, ascii);
758 /* Try getting the character again from the list */
759 che = vfd->characters.first;
761 if(che->index == ascii)
770 MEM_freeN(chartransdata);
774 if (vfont != oldvfont) {
775 vfd= vfont_get_data(vfont);
779 /* VFont Data for VFont couldn't be found */
783 MEM_freeN(chartransdata);
787 // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
793 // Calculate positions
794 if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) {
795 // fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
796 for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
797 if (mem[j]==' ' || mem[j]=='-') {
800 if (mem[j] == ' ') wsnr--;
801 if (mem[j] == '-') wsnr++;
805 custrinfo[i+1].flag |= CU_WRAP;
808 if (chartransdata[j].dobreak) {
809 // fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
811 custrinfo[i+1].flag |= CU_WRAP;
820 if(ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
828 maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize));
829 linedata[lnr]= xof-tb->x/cu->fsize;
831 linedata3[lnr]= tb->w/cu->fsize;
832 linedata4[lnr]= wsnr;
834 if ( (tb->h != 0.0) &&
835 ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize))) &&
836 (cu->totbox > (curbox+1)) ) {
840 yof= cu->yof + tb->y/cu->fsize;
843 if(ascii == '\n' || ascii == '\r')
846 xof= cu->xof + (tb->x/cu->fsize);
848 xof= cu->xof + (tb->x/cu->fsize);
853 else if(ascii==9) { /* TAB */
861 tabfac= (xof-cu->xof+0.01f);
862 tabfac= (float)(2.0*ceil(tabfac/2.0));
874 if (cu->selboxes && (i>=selstart) && (i<=selend)) {
875 sb = &(cu->selboxes[i-selstart]);
876 sb->y = yof*cu->fsize-linedist*cu->fsize*0.1;
877 sb->h = linedist*cu->fsize;
878 sb->w = xof*cu->fsize;
882 wsfac = cu->wordspace;
887 // Set the width of the character
893 xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
896 sb->w = (xof*cu->fsize) - sb->w;
904 for (i= 0; i<=slen; i++, tmp++, ct++) {
906 if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
909 // linedata is now: width of line
910 // linedata2 is now: number of characters
911 // linedata3 is now: maxlen of that line
912 // linedata4 is now: number of whitespaces of line
914 if(cu->spacemode!=CU_LEFT) {
917 if(cu->spacemode==CU_RIGHT) {
918 for(i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i];
919 for (i=0; i<=slen; i++) {
920 ct->xof+= linedata[ct->linenr];
923 } else if(cu->spacemode==CU_MIDDLE) {
924 for(i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2;
925 for (i=0; i<=slen; i++) {
926 ct->xof+= linedata[ct->linenr];
929 } else if((cu->spacemode==CU_FLUSH) &&
930 (cu->tb[0].w != 0.0)) {
933 linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
934 for (i=0; i<=slen; i++) {
935 for (j=i; (mem[j]) && (mem[j]!='\n') &&
936 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
937 // if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
938 ct->xof+= ct->charnr*linedata[ct->linenr];
943 else if((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0)) {
945 for (i=0; i<=slen; i++) {
946 for (j=i; (mem[j]) && (mem[j]!='\n') &&
947 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
948 if ((mem[j]!='\r') && (mem[j]!='\n') &&
949 ((chartransdata[j].dobreak!=0))) {
950 if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
953 if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
960 /* Note: Only OB_CURVE objects could have a path */
961 if(cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
962 Curve *cucu= cu->textoncurve->data;
963 int oldflag= cucu->flag;
965 cucu->flag |= (CU_PATH+CU_FOLLOW);
967 if(cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0);
969 float distfac, imat[4][4], imat3[3][3], cmat[3][3];
970 float minx, maxx, miny, maxy;
971 float timeofs, sizefac;
973 invert_m4_m4(imat, ob->obmat);
974 copy_m3_m4(imat3, imat);
976 copy_m3_m4(cmat, cu->textoncurve->obmat);
977 mul_m3_m3m3(cmat, cmat, imat3);
978 sizefac= normalize_v3(cmat[0])/cu->fsize;
983 for (i=0; i<=slen; i++, ct++) {
984 if(minx>ct->xof) minx= ct->xof;
985 if(maxx<ct->xof) maxx= ct->xof;
986 if(miny>ct->yof) miny= ct->yof;
987 if(maxy<ct->yof) maxy= ct->yof;
990 /* we put the x-coordinaat exact at the curve, the y is rotated */
992 /* length correction */
993 distfac= sizefac*cucu->path->totdist/(maxx-minx);
997 /* path longer than text: spacemode involves */
998 distfac= 1.0f/distfac;
1000 if(cu->spacemode==CU_RIGHT) {
1001 timeofs= 1.0f-distfac;
1003 else if(cu->spacemode==CU_MIDDLE) {
1004 timeofs= (1.0f-distfac)/2.0f;
1006 else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
1011 distfac/= (maxx-minx);
1013 timeofs+= distfac*cu->xof; /* not cyclic */
1016 for (i=0; i<=slen; i++, ct++) {
1017 float ctime, dtime, vec[4], tvec[4], rotvec[3];
1020 /* rotate around center character */
1023 // Find the character
1024 che = vfd->characters.first;
1026 if(che->index == ascii)
1032 twidth = che->width;
1036 dtime= distfac*0.35f*twidth; /* why not 0.5? */
1037 dtime= distfac*0.5f*twidth; /* why not 0.5? */
1039 ctime= timeofs + distfac*( ct->xof - minx);
1040 CLAMP(ctime, 0.0, 1.0);
1042 /* calc the right loc AND the right rot separately */
1043 /* vec, tvec need 4 items */
1044 where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL);
1045 where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL);
1047 mul_v3_fl(vec, sizefac);
1049 ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
1051 si= (float)sin(ct->rot);
1052 co= (float)cos(ct->rot);
1056 ct->xof= vec[0] + si*yof;
1057 ct->yof= vec[1] + co*yof;
1060 cucu->flag= oldflag;
1066 for (i=0; i<=selend; i++, ct++) {
1068 cu->selboxes[i-selstart].x = ct->xof*cu->fsize;
1069 cu->selboxes[i-selstart].y = ct->yof*cu->fsize;
1074 if(mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) {
1077 ct= chartransdata+cu->pos;
1079 if((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0);
1080 else if((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr);
1083 case FO_CURSUP: lnr= ct->linenr-1; break;
1084 case FO_CURSDOWN: lnr= ct->linenr+1; break;
1085 case FO_PAGEUP: lnr= ct->linenr-10; break;
1086 case FO_PAGEDOWN: lnr= ct->linenr+10; break;
1089 /* seek for char with lnr en cnr */
1092 for (i= 0; i<slen; i++) {
1093 if(ct->linenr==lnr) {
1094 if(ct->charnr==cnr) break;
1095 if( (ct+1)->charnr==0) break;
1097 else if(ct->linenr>lnr) break;
1108 ct= chartransdata+cu->pos;
1109 si= (float)sin(ct->rot);
1110 co= (float)cos(ct->rot);
1112 f= cu->editfont->textcurs[0];
1114 f[0]= cu->fsize*(-0.1f*co + ct->xof);
1115 f[1]= cu->fsize*(0.1f*si + ct->yof);
1117 f[2]= cu->fsize*(0.1f*co + ct->xof);
1118 f[3]= cu->fsize*(-0.1f*si + ct->yof);
1120 f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
1121 f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
1123 f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
1124 f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
1128 MEM_freeN(linedata);
1129 MEM_freeN(linedata2);
1130 MEM_freeN(linedata3);
1131 MEM_freeN(linedata4);
1133 if (mode == FO_SELCHANGE) {
1134 MEM_freeN(chartransdata);
1143 freeNurblist(&cu->nurb);
1146 if (cu->sepchar==0) {
1147 for (i= 0; i<slen; i++) {
1148 cha = (uintptr_t) mem[i];
1149 info = &(custrinfo[i]);
1150 if (info->mat_nr > (ob->totcol)) {
1151 /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
1154 // We do not want to see any character for \n or \r
1155 if(cha != '\n' && cha != '\r')
1156 buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i);
1158 if ((info->flag & CU_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
1159 float ulwidth, uloverlap= 0.0f;
1161 if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
1162 ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_UNDERLINE)) && ((custrinfo[i+1].flag & CU_WRAP)==0)
1164 uloverlap = xtrax + 0.1;
1166 // Find the character, the characters has to be in the memory already
1167 // since character checking has been done earlier already.
1168 che = vfd->characters.first;
1170 if(che->index == cha)
1175 if(!che) twidth =0; else twidth=che->width;
1176 ulwidth = cu->fsize * ((twidth* (1.0+(info->kern/40.0)))+uloverlap);
1177 build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize,
1178 ct->xof*cu->fsize + ulwidth,
1179 ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize,
1187 for (i= 0; (i<slen) && (outta==0); i++) {
1189 info = &(custrinfo[i]);
1190 if (cu->sepchar == (i+1)) {
1195 custrinfo[0]= *info;
1201 mul_m4_v3(ob->obmat, vecyo);
1202 VECCOPY(ob->loc, vecyo);
1211 if(mode==FO_DUPLI) {
1213 return chartransdata;
1219 MEM_freeN(chartransdata);