Blender V2.61 - r43446

font.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <math.h>
00036 #include <stdlib.h>
00037 #include <wchar.h>
00038 #include <wctype.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_math.h"
00043 #include "BLI_blenlib.h"
00044 #include "BLI_vfontdata.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "DNA_packedFile_types.h"
00048 #include "DNA_curve_types.h"
00049 #include "DNA_vfont_types.h"
00050 #include "DNA_scene_types.h"
00051 #include "DNA_object_types.h"
00052 
00053 #include "BKE_utildefines.h"
00054 #include "BKE_packedFile.h"
00055 #include "BKE_library.h"
00056 #include "BKE_font.h"
00057 #include "BKE_global.h"
00058 #include "BKE_main.h"
00059 #include "BKE_anim.h"
00060 #include "BKE_curve.h"
00061 #include "BKE_displist.h"
00062 
00063 static ListBase ttfdata= {NULL, NULL};
00064 
00065 /* The vfont code */
00066 void free_vfont(struct VFont *vf)
00067 {
00068     if (vf == NULL) return;
00069 
00070     if (vf->data) {
00071         while(vf->data->characters.first)
00072         {
00073             VChar *che = vf->data->characters.first;
00074             
00075             while (che->nurbsbase.first) {
00076                 Nurb *nu = che->nurbsbase.first;
00077                 if (nu->bezt) MEM_freeN(nu->bezt);
00078                 BLI_freelinkN(&che->nurbsbase, nu);
00079             }
00080     
00081             BLI_freelinkN(&vf->data->characters, che);
00082         }
00083 
00084         MEM_freeN(vf->data);
00085         vf->data = NULL;
00086     }
00087     
00088     if (vf->packedfile) {
00089         freePackedFile(vf->packedfile);
00090         vf->packedfile = NULL;
00091     }
00092 }
00093 
00094 static void *builtin_font_data= NULL;
00095 static int builtin_font_size= 0;
00096 
00097 void BKE_font_register_builtin(void *mem, int size)
00098 {
00099     builtin_font_data= mem;
00100     builtin_font_size= size;
00101 }
00102 
00103 static PackedFile *get_builtin_packedfile(void)
00104 {
00105     if (!builtin_font_data) {
00106         printf("Internal error, builtin font not loaded\n");
00107 
00108         return NULL;
00109     } else {
00110         void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
00111 
00112         memcpy(mem, builtin_font_data, builtin_font_size);
00113     
00114         return newPackedFileMemory(mem, builtin_font_size);
00115     }
00116 }
00117 
00118 void free_ttfont(void)
00119 {
00120     struct TmpFont *tf;
00121 
00122     for(tf= ttfdata.first; tf; tf= tf->next) {
00123         if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
00124         tf->pf= NULL;
00125         tf->vfont= NULL;
00126     }
00127     BLI_freelistN(&ttfdata);
00128 }
00129 
00130 struct TmpFont *vfont_find_tmpfont(VFont *vfont)
00131 {
00132     struct TmpFont *tmpfnt = NULL;
00133     
00134     if(vfont==NULL) return NULL;
00135     
00136     // Try finding the font from font list
00137     tmpfnt = ttfdata.first;
00138     while(tmpfnt)
00139     {
00140         if(tmpfnt->vfont == vfont)
00141             break;
00142         tmpfnt = tmpfnt->next;
00143     }
00144     return tmpfnt;
00145 }
00146 
00147 static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
00148 {
00149     struct TmpFont *tmpfnt = NULL;
00150     PackedFile *tpf;
00151     
00152     if(vfont==NULL) return NULL;
00153     
00154     // Try finding the font from font list
00155     tmpfnt = vfont_find_tmpfont(vfont);
00156     
00157     // And then set the data    
00158     if (!vfont->data) {
00159         PackedFile *pf;
00160         
00161         if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) {
00162             pf= get_builtin_packedfile();
00163         } else {
00164             if (vfont->packedfile) {
00165                 pf= vfont->packedfile;
00166                 
00167                 // We need to copy a tmp font to memory unless it is already there
00168                 if(!tmpfnt)
00169                 {
00170                     tpf= MEM_callocN(sizeof(*tpf), "PackedFile");
00171                     tpf->data= MEM_mallocN(pf->size, "packFile");
00172                     tpf->size= pf->size;
00173                     memcpy(tpf->data, pf->data, pf->size);
00174                     
00175                     // Add temporary packed file to globals
00176                     tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
00177                     tmpfnt->pf= tpf;
00178                     tmpfnt->vfont= vfont;
00179                     BLI_addtail(&ttfdata, tmpfnt);
00180                 }
00181             } else {
00182                 pf= newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
00183                 
00184                 if(!tmpfnt)
00185                 {
00186                     tpf= newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
00187                     
00188                     // Add temporary packed file to globals
00189                     tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
00190                     tmpfnt->pf= tpf;
00191                     tmpfnt->vfont= vfont;
00192                     BLI_addtail(&ttfdata, tmpfnt);
00193                 }
00194             }
00195             if(!pf) {
00196                 printf("Font file doesn't exist: %s\n", vfont->name);
00197 
00198                 strcpy(vfont->name, FO_BUILTIN_NAME);
00199                 pf= get_builtin_packedfile();
00200             }
00201         }
00202         
00203         if (pf) {
00204             vfont->data= BLI_vfontdata_from_freetypefont(pf);
00205             if (pf != vfont->packedfile) {
00206                 freePackedFile(pf);
00207             }
00208         }
00209     }
00210     
00211     return vfont->data; 
00212 }
00213 
00214 VFont *load_vfont(Main *bmain, const char *name)
00215 {
00216     char filename[FILE_MAXFILE];
00217     VFont *vfont= NULL;
00218     PackedFile *pf;
00219     PackedFile *tpf = NULL; 
00220     int is_builtin;
00221     struct TmpFont *tmpfnt;
00222     
00223     if (strcmp(name, FO_BUILTIN_NAME)==0) {
00224         BLI_strncpy(filename, name, sizeof(filename));
00225         
00226         pf= get_builtin_packedfile();
00227         is_builtin= 1;
00228     } else {
00229         char dir[FILE_MAXDIR];
00230         
00231         BLI_strncpy(dir, name, sizeof(dir));
00232         BLI_splitdirstring(dir, filename);
00233 
00234         pf= newPackedFile(NULL, name, bmain->name);
00235         tpf= newPackedFile(NULL, name, bmain->name);
00236         
00237         is_builtin= 0;
00238     }
00239 
00240     if (pf) {
00241         VFontData *vfd;
00242 
00243         vfd= BLI_vfontdata_from_freetypefont(pf);
00244         if (vfd) {
00245             vfont = alloc_libblock(&bmain->vfont, ID_VF, filename);
00246             vfont->data = vfd;
00247 
00248             /* if there's a font name, use it for the ID name */
00249             if (vfd->name[0] != '\0') {
00250                 BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2);
00251             }
00252             BLI_strncpy(vfont->name, name, sizeof(vfont->name));
00253 
00254             // if autopack is on store the packedfile in de font structure
00255             if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
00256                 vfont->packedfile = pf;
00257             }
00258             
00259             // Do not add FO_BUILTIN_NAME to temporary listbase
00260             if(strcmp(filename, FO_BUILTIN_NAME))
00261             {
00262                 tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
00263                 tmpfnt->pf= tpf;
00264                 tmpfnt->vfont= vfont;
00265                 BLI_addtail(&ttfdata, tmpfnt);
00266             }           
00267         }
00268         
00269         // Free the packed file
00270         if (!vfont || vfont->packedfile != pf) {
00271             freePackedFile(pf);
00272         }
00273     
00274         //XXX waitcursor(0);
00275     }
00276     
00277     return vfont;
00278 }
00279 
00280 static VFont *which_vfont(Curve *cu, CharInfo *info)
00281 {
00282     switch(info->flag & (CU_CHINFO_BOLD|CU_CHINFO_ITALIC)) {
00283         case CU_CHINFO_BOLD:
00284             if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
00285         case CU_CHINFO_ITALIC:
00286             if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
00287         case (CU_CHINFO_BOLD|CU_CHINFO_ITALIC):
00288             if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
00289         default:
00290             return(cu->vfont);
00291     }           
00292 }
00293 
00294 VFont *get_builtin_font(void)
00295 {
00296     VFont *vf;
00297     
00298     for (vf= G.main->vfont.first; vf; vf= vf->id.next)
00299         if (strcmp(vf->name, FO_BUILTIN_NAME)==0)
00300             return vf;
00301     
00302     return load_vfont(G.main, FO_BUILTIN_NAME);
00303 }
00304 
00305 static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
00306 {
00307     VChar *che= NULL;
00308 
00309     for(che = vfd->characters.first; che; che = che->next) {
00310         if(che->index == character)
00311             break;
00312     }
00313     return che; /* NULL if not found */
00314 }
00315         
00316 static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr)
00317 {
00318     Nurb *nu2;
00319     BPoint *bp;
00320     
00321     nu2 =(Nurb*) MEM_callocN(sizeof(Nurb),"underline_nurb");
00322     if (nu2 == NULL) return;
00323     nu2->resolu= cu->resolu;
00324     nu2->bezt = NULL;
00325     nu2->knotsu = nu2->knotsv = NULL;
00326     nu2->flag= CU_2D;
00327     nu2->charidx = charidx+1000;
00328     if (mat_nr > 0) nu2->mat_nr= mat_nr-1;
00329     nu2->pntsu = 4;
00330     nu2->pntsv = 1;
00331     nu2->orderu = 4;
00332     nu2->orderv = 1;
00333     nu2->flagu = CU_NURB_CYCLIC;
00334 
00335     bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); 
00336     if (bp == NULL){
00337         MEM_freeN(nu2);
00338         return;
00339     }
00340     nu2->bp = bp;
00341 
00342     nu2->bp[0].vec[0] = x1;
00343     nu2->bp[0].vec[1] = y1; 
00344     nu2->bp[0].vec[2] = 0;
00345     nu2->bp[0].vec[3] = 1.0f;
00346     nu2->bp[1].vec[0] = x2;
00347     nu2->bp[1].vec[1] = y1;
00348     nu2->bp[1].vec[2] = 0;  
00349     nu2->bp[1].vec[3] = 1.0f;
00350     nu2->bp[2].vec[0] = x2;
00351     nu2->bp[2].vec[1] = y2; 
00352     nu2->bp[2].vec[2] = 0;
00353     nu2->bp[2].vec[3] = 1.0f;
00354     nu2->bp[3].vec[0] = x1;
00355     nu2->bp[3].vec[1] = y2;
00356     nu2->bp[3].vec[2] = 0;  
00357     nu2->bp[3].vec[3] = 1.0f;
00358     
00359     BLI_addtail(&(cu->nurb), nu2);  
00360 
00361 }
00362 
00363 static void buildchar(Main *bmain, Curve *cu, unsigned long character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
00364 {
00365     BezTriple *bezt1, *bezt2;
00366     Nurb *nu1 = NULL, *nu2 = NULL;
00367     float *fp, fsize, shear, x, si, co;
00368     VFontData *vfd = NULL;
00369     VChar *che = NULL;
00370     int i;
00371 
00372     vfd= vfont_get_data(bmain, which_vfont(cu, info));
00373     if (!vfd) return;
00374 
00375     /*
00376     if (cu->selend < cu->selstart) {
00377         if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
00378             sel= 1;
00379     }
00380     else {
00381         if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
00382             sel= 1;
00383     }
00384     */
00385 
00386     /* make a copy at distance ofsx,ofsy with shear*/
00387     fsize= cu->fsize;
00388     shear= cu->shear;
00389     si= (float)sin(rot);
00390     co= (float)cos(rot);
00391 
00392     che= find_vfont_char(vfd, character);
00393     
00394     // Select the glyph data
00395     if(che)
00396         nu1 = che->nurbsbase.first;
00397 
00398     // Create the character
00399     while(nu1)
00400     {
00401         bezt1 = nu1->bezt;
00402         if (bezt1){
00403             nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
00404             if (nu2 == NULL) break;
00405             memcpy(nu2, nu1, sizeof(struct Nurb));
00406             nu2->resolu= cu->resolu;
00407             nu2->bp = NULL;
00408             nu2->knotsu = nu2->knotsv = NULL;
00409             nu2->flag= CU_SMOOTH;
00410             nu2->charidx = charidx;
00411             if (info->mat_nr > 0) {
00412                 nu2->mat_nr= info->mat_nr-1;
00413             }
00414             else {
00415                 nu2->mat_nr= 0;
00416             }
00417             /* nu2->trim.first = 0; */
00418             /* nu2->trim.last = 0; */
00419             i = nu2->pntsu;
00420 
00421             bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2"); 
00422             if (bezt2 == NULL){
00423                 MEM_freeN(nu2);
00424                 break;
00425             }
00426             memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
00427             nu2->bezt = bezt2;
00428             
00429             if (shear != 0.0f) {
00430                 bezt2 = nu2->bezt;
00431                 
00432                 for (i= nu2->pntsu; i > 0; i--) {
00433                     bezt2->vec[0][0] += shear * bezt2->vec[0][1];
00434                     bezt2->vec[1][0] += shear * bezt2->vec[1][1];
00435                     bezt2->vec[2][0] += shear * bezt2->vec[2][1];
00436                     bezt2++;
00437                 }
00438             }
00439             if(rot != 0.0f) {
00440                 bezt2= nu2->bezt;
00441                 for (i=nu2->pntsu; i > 0; i--) {
00442                     fp= bezt2->vec[0];
00443                     
00444                     x= fp[0];
00445                     fp[0]= co*x + si*fp[1];
00446                     fp[1]= -si*x + co*fp[1];
00447                     x= fp[3];
00448                     fp[3]= co*x + si*fp[4];
00449                     fp[4]= -si*x + co*fp[4];
00450                     x= fp[6];
00451                     fp[6]= co*x + si*fp[7];
00452                     fp[7]= -si*x + co*fp[7];
00453 
00454                     bezt2++;
00455                 }
00456             }
00457             bezt2 = nu2->bezt;
00458 
00459             if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
00460                 const float sca= cu->smallcaps_scale;
00461                 for (i= nu2->pntsu; i > 0; i--) {
00462                     fp= bezt2->vec[0];
00463                     fp[0] *= sca;
00464                     fp[1] *= sca;
00465                     fp[3] *= sca;
00466                     fp[4] *= sca;
00467                     fp[6] *= sca;
00468                     fp[7] *= sca;
00469                     bezt2++;
00470                 }
00471             }
00472             bezt2 = nu2->bezt;
00473 
00474             for (i= nu2->pntsu; i > 0; i--) {
00475                 fp= bezt2->vec[0];
00476                 fp[0]= (fp[0]+ofsx)*fsize;
00477                 fp[1]= (fp[1]+ofsy)*fsize;
00478                 fp[3]= (fp[3]+ofsx)*fsize;
00479                 fp[4]= (fp[4]+ofsy)*fsize;
00480                 fp[6]= (fp[6]+ofsx)*fsize;
00481                 fp[7]= (fp[7]+ofsy)*fsize;
00482                 bezt2++;
00483             }
00484             
00485             BLI_addtail(&(cu->nurb), nu2);
00486         }
00487         
00488         nu1 = nu1->next;
00489     }
00490 }
00491 
00492 int BKE_font_getselection(Object *ob, int *start, int *end)
00493 {
00494     Curve *cu= ob->data;
00495     
00496     if (cu->editfont==NULL || ob->type != OB_FONT) return 0;
00497 
00498     if (cu->selstart == 0) return 0;
00499     if (cu->selstart <= cu->selend) {
00500         *start = cu->selstart-1;
00501         *end = cu->selend-1;
00502         return 1;
00503     }
00504     else {
00505         *start = cu->selend;
00506         *end = cu->selstart-2;
00507         return -1;
00508     }
00509 }
00510 
00511 static float char_width(Curve *cu, VChar *che, CharInfo *info)
00512 {
00513     // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
00514     if(che == NULL) {
00515         return 0.0f;
00516     }
00517     else if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
00518         return che->width * cu->smallcaps_scale;
00519     }
00520     else {
00521         return che->width;
00522     }
00523 }
00524 
00525 struct chartrans *BKE_text_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
00526 {
00527     VFont *vfont, *oldvfont;
00528     VFontData *vfd= NULL;
00529     Curve *cu;
00530     CharInfo *info = NULL, *custrinfo;
00531     TextBox *tb;
00532     VChar *che;
00533     struct chartrans *chartransdata=NULL, *ct;
00534     float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
00535     float twidth, maxlen= 0;
00536     int i, slen, j;
00537     int curbox;
00538     int selstart, selend;
00539     int utf8len;
00540     short cnr=0, lnr=0, wsnr= 0;
00541     wchar_t *mem, *tmp, ascii;
00542 
00543     /* renark: do calculations including the trailing '\0' of a string
00544        because the cursor can be at that location */
00545 
00546     if(ob->type!=OB_FONT) return NULL;
00547 
00548     // Set font data
00549     cu= (Curve *) ob->data;
00550     vfont= cu->vfont;
00551     
00552     if(cu->str == NULL) return NULL;
00553     if(vfont == NULL) return NULL;
00554 
00555     // Create unicode string
00556     utf8len = BLI_strlen_utf8(cu->str);
00557     mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
00558     
00559     BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1);
00560 
00561     // Count the wchar_t string length
00562     slen = wcslen(mem);
00563 
00564     if (cu->ulheight == 0.0f)
00565         cu->ulheight = 0.05f;
00566     
00567     if (cu->strinfo==NULL)  /* old file */
00568         cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat");
00569     
00570     custrinfo= cu->strinfo;
00571     if (cu->editfont)
00572         custrinfo= cu->editfont->textbufinfo;
00573     
00574     if (cu->tb==NULL)
00575         cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat");
00576 
00577     vfd= vfont_get_data(bmain, vfont);
00578 
00579     /* The VFont Data can not be found */
00580     if(!vfd) {
00581         if(mem)
00582             MEM_freeN(mem); 
00583         return NULL;
00584     }
00585 
00586     /* calc offset and rotation of each char */
00587     ct = chartransdata =
00588         (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
00589 
00590     /* We assume the worst case: 1 character per line (is freed at end anyway) */
00591 
00592     linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
00593     linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
00594     linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");    
00595     linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");        
00596     
00597     linedist= cu->linedist;
00598     
00599     xof= cu->xof + (cu->tb[0].x/cu->fsize);
00600     yof= cu->yof + (cu->tb[0].y/cu->fsize);
00601 
00602     xtrax= 0.5f*cu->spacing-0.5f;
00603 
00604     oldvfont = NULL;
00605 
00606     for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK);
00607 
00608     if (cu->selboxes) MEM_freeN(cu->selboxes);
00609     cu->selboxes = NULL;
00610     if (BKE_font_getselection(ob, &selstart, &selend))
00611         cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
00612 
00613     tb = &(cu->tb[0]);
00614     curbox= 0;
00615     for (i = 0 ; i<=slen ; i++) {
00616     makebreak:
00617         // Characters in the list
00618         info = &(custrinfo[i]);
00619         ascii = mem[i];
00620         if(info->flag & CU_CHINFO_SMALLCAPS) {
00621             ascii = towupper(ascii);
00622             if(mem[i] != ascii) {
00623                 mem[i]= ascii;
00624                 info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
00625             }
00626         }
00627 
00628         vfont = which_vfont(cu, info);
00629         
00630         if(vfont==NULL) break;
00631 
00632         che= find_vfont_char(vfd, ascii);
00633 
00634         /*
00635          * The character wasn't in the current curve base so load it
00636          * But if the font is FO_BUILTIN_NAME then do not try loading since
00637          * whole font is in the memory already
00638          */
00639         if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) {
00640             BLI_vfontchar_from_freetypefont(vfont, ascii);
00641         }
00642 
00643         /* Try getting the character again from the list */
00644         che= find_vfont_char(vfd, ascii);
00645 
00646         /* No VFont found */
00647         if (vfont==NULL) {
00648             if(mem)
00649                 MEM_freeN(mem);
00650             MEM_freeN(chartransdata);
00651             return NULL;
00652         }
00653 
00654         if (vfont != oldvfont) {
00655             vfd= vfont_get_data(bmain, vfont);
00656             oldvfont = vfont;
00657         }
00658 
00659         /* VFont Data for VFont couldn't be found */
00660         if (!vfd) {
00661             if(mem)
00662                 MEM_freeN(mem);
00663             MEM_freeN(chartransdata);
00664             return NULL;
00665         }
00666 
00667         twidth = char_width(cu, che, info);
00668 
00669         // Calculate positions
00670         if((tb->w != 0.0f) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) {
00671     //      fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
00672             for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
00673                 if (mem[j]==' ' || mem[j]=='-') {
00674                     ct -= (i-(j-1));
00675                     cnr -= (i-(j-1));
00676                     if (mem[j] == ' ') wsnr--;
00677                     if (mem[j] == '-') wsnr++;
00678                     i = j-1;
00679                     xof = ct->xof;
00680                     ct[1].dobreak = 1;
00681                     custrinfo[i+1].flag |= CU_CHINFO_WRAP;
00682                     goto makebreak;
00683                 }
00684                 if (chartransdata[j].dobreak) {
00685     //              fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
00686                     ct->dobreak= 1;
00687                     custrinfo[i+1].flag |= CU_CHINFO_WRAP;
00688                     ct -= 1;
00689                     cnr -= 1;
00690                     i--;
00691                     xof = ct->xof;
00692                     goto makebreak;
00693                 }
00694             }
00695         }
00696         if(ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
00697             ct->xof= xof;
00698             ct->yof= yof;
00699             ct->linenr= lnr;
00700             ct->charnr= cnr;
00701             
00702             yof-= linedist;
00703             
00704             maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize));
00705             linedata[lnr]= xof-tb->x/cu->fsize;
00706             linedata2[lnr]= cnr;
00707             linedata3[lnr]= tb->w/cu->fsize;
00708             linedata4[lnr]= wsnr;
00709             
00710             if ( (tb->h != 0.0f) &&
00711                  ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) &&
00712                  (cu->totbox > (curbox+1)) ) {
00713                 maxlen= 0;
00714                 tb++;
00715                 curbox++;
00716                 yof= cu->yof + tb->y/cu->fsize;
00717             }
00718 
00719             /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
00720 #if 0
00721             if(ascii == '\n' || ascii == '\r')
00722                 xof = cu->xof;
00723             else
00724                 xof= cu->xof + (tb->x/cu->fsize);
00725 #else
00726             xof= cu->xof + (tb->x/cu->fsize);
00727 #endif
00728             lnr++;
00729             cnr= 0;
00730             wsnr= 0;
00731         }
00732         else if(ascii==9) { /* TAB */
00733             float tabfac;
00734             
00735             ct->xof= xof;
00736             ct->yof= yof;
00737             ct->linenr= lnr;
00738             ct->charnr= cnr++;
00739 
00740             tabfac= (xof-cu->xof+0.01f);
00741             tabfac= 2.0f*ceilf(tabfac/2.0f);
00742             xof= cu->xof+tabfac;
00743         }
00744         else {
00745             SelBox *sb= NULL;
00746             float wsfac;
00747 
00748             ct->xof= xof;
00749             ct->yof= yof;
00750             ct->linenr= lnr;
00751             ct->charnr= cnr++;
00752 
00753             if (cu->selboxes && (i>=selstart) && (i<=selend)) {
00754                 sb = &(cu->selboxes[i-selstart]);
00755                 sb->y = yof*cu->fsize-linedist*cu->fsize*0.1f;
00756                 sb->h = linedist*cu->fsize;
00757                 sb->w = xof*cu->fsize;
00758             }
00759     
00760             if (ascii==32) {
00761                 wsfac = cu->wordspace; 
00762                 wsnr++;
00763             } 
00764             else wsfac = 1.0f;
00765             
00766             // Set the width of the character
00767             twidth = char_width(cu, che, info);
00768 
00769             xof += (twidth*wsfac*(1.0f+(info->kern/40.0f)) ) + xtrax;
00770             
00771             if (sb) 
00772                 sb->w = (xof*cu->fsize) - sb->w;
00773         }
00774         ct++;
00775     }
00776     
00777     cu->lines= 1;
00778     ct= chartransdata;
00779     tmp = mem;
00780     for (i= 0; i<=slen; i++, tmp++, ct++) {
00781         ascii = *tmp;
00782         if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
00783     }   
00784 
00785     // linedata is now: width of line
00786     // linedata2 is now: number of characters
00787     // linedata3 is now: maxlen of that line
00788     // linedata4 is now: number of whitespaces of line
00789 
00790     if(cu->spacemode!=CU_LEFT) {
00791         ct= chartransdata;
00792 
00793         if(cu->spacemode==CU_RIGHT) {
00794             for(i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i];
00795             for (i=0; i<=slen; i++) {
00796                 ct->xof+= linedata[ct->linenr];
00797                 ct++;
00798             }
00799         } else if(cu->spacemode==CU_MIDDLE) {
00800             for(i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2;
00801             for (i=0; i<=slen; i++) {
00802                 ct->xof+= linedata[ct->linenr];
00803                 ct++;
00804             }
00805         } else if((cu->spacemode==CU_FLUSH) &&
00806                   (cu->tb[0].w != 0.0f)) {
00807             for(i=0;i<lnr;i++)
00808                 if(linedata2[i]>1)
00809                     linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
00810             for (i=0; i<=slen; i++) {
00811                 for (j=i; (mem[j]) && (mem[j]!='\n') && 
00812                           (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
00813 //              if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
00814                     ct->xof+= ct->charnr*linedata[ct->linenr];
00815 //              }
00816                 ct++;
00817             }
00818         } 
00819         else if((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
00820             float curofs= 0.0f;
00821             for (i=0; i<=slen; i++) {
00822                 for (j=i; (mem[j]) && (mem[j]!='\n') && 
00823                           (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
00824                 if ((mem[j]!='\r') && (mem[j]!='\n') &&
00825                     ((chartransdata[j].dobreak!=0))) {
00826                     if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
00827                     ct->xof+= curofs;
00828                 }
00829                 if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
00830                 ct++;
00831             }           
00832         }
00833     }
00834     
00835     /* TEXT ON CURVE */
00836     /* Note: Only OB_CURVE objects could have a path  */
00837     if(cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
00838         Curve *cucu= cu->textoncurve->data;
00839         int oldflag= cucu->flag;
00840         
00841         cucu->flag |= (CU_PATH+CU_FOLLOW);
00842         
00843         if(cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0);
00844         if(cucu->path) {
00845             float distfac, imat[4][4], imat3[3][3], cmat[3][3];
00846             float minx, maxx, miny, maxy;
00847             float timeofs, sizefac;
00848             
00849             invert_m4_m4(imat, ob->obmat);
00850             copy_m3_m4(imat3, imat);
00851 
00852             copy_m3_m4(cmat, cu->textoncurve->obmat);
00853             mul_m3_m3m3(cmat, cmat, imat3);
00854             sizefac= normalize_v3(cmat[0])/cu->fsize;
00855             
00856             minx=miny= 1.0e20f;
00857             maxx=maxy= -1.0e20f;
00858             ct= chartransdata;
00859             for (i=0; i<=slen; i++, ct++) {
00860                 if(minx>ct->xof) minx= ct->xof;
00861                 if(maxx<ct->xof) maxx= ct->xof;
00862                 if(miny>ct->yof) miny= ct->yof;
00863                 if(maxy<ct->yof) maxy= ct->yof;
00864             }
00865             
00866             /* we put the x-coordinaat exact at the curve, the y is rotated */
00867             
00868             /* length correction */
00869             distfac= sizefac*cucu->path->totdist/(maxx-minx);
00870             timeofs= 0.0f;
00871             
00872             if(distfac > 1.0f) {
00873                 /* path longer than text: spacemode involves */
00874                 distfac= 1.0f/distfac;
00875                 
00876                 if(cu->spacemode==CU_RIGHT) {
00877                     timeofs= 1.0f-distfac;
00878                 }
00879                 else if(cu->spacemode==CU_MIDDLE) {
00880                     timeofs= (1.0f-distfac)/2.0f;
00881                 }
00882                 else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
00883                 
00884             }
00885             else distfac= 1.0;
00886             
00887             distfac/= (maxx-minx);
00888             
00889             timeofs+= distfac*cu->xof;  /* not cyclic */
00890             
00891             ct= chartransdata;
00892             for (i=0; i<=slen; i++, ct++) {
00893                 float ctime, dtime, vec[4], tvec[4], rotvec[3];
00894                 float si, co;
00895                 
00896                 /* rotate around center character */
00897                 ascii = mem[i];
00898 
00899                 che= find_vfont_char(vfd, ascii);
00900     
00901                 twidth = char_width(cu, che, info);
00902 
00903                 dtime= distfac*0.5f*twidth;
00904 
00905                 ctime= timeofs + distfac*( ct->xof - minx);
00906                 CLAMP(ctime, 0.0f, 1.0f);
00907 
00908                 /* calc the right loc AND the right rot separately */
00909                 /* vec, tvec need 4 items */
00910                 where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
00911                 where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL);
00912                 
00913                 mul_v3_fl(vec, sizefac);
00914                 
00915                 ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
00916 
00917                 si= (float)sin(ct->rot);
00918                 co= (float)cos(ct->rot);
00919 
00920                 yof= ct->yof;
00921                 
00922                 ct->xof= vec[0] + si*yof;
00923                 ct->yof= vec[1] + co*yof;
00924                 
00925             }
00926             cucu->flag= oldflag;
00927         }
00928     }
00929 
00930     if (cu->selboxes) {
00931         ct= chartransdata;
00932         for (i=0; i<=selend; i++, ct++) {
00933             if (i>=selstart) {
00934                 cu->selboxes[i-selstart].x = ct->xof*cu->fsize;
00935                 cu->selboxes[i-selstart].y = ct->yof*cu->fsize;             
00936             }
00937         }
00938     }
00939 
00940     if(mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) {
00941         /* 2: curs up
00942            3: curs down */
00943         ct= chartransdata+cu->pos;
00944         
00945         if((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0);
00946         else if((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr);
00947         else {
00948             switch(mode) {
00949                 case FO_CURSUP:     lnr= ct->linenr-1; break;
00950                 case FO_CURSDOWN:   lnr= ct->linenr+1; break;
00951                 case FO_PAGEUP:     lnr= ct->linenr-10; break;
00952                 case FO_PAGEDOWN:   lnr= ct->linenr+10; break;
00953             }
00954             cnr= ct->charnr;
00955             /* seek for char with lnr en cnr */
00956             cu->pos= 0;
00957             ct= chartransdata;
00958             for (i= 0; i<slen; i++) {
00959                 if(ct->linenr==lnr) {
00960                     if(ct->charnr==cnr) break;
00961                     if( (ct+1)->charnr==0) break;
00962                 }
00963                 else if(ct->linenr>lnr) break;
00964                 cu->pos++;
00965                 ct++;
00966             }
00967         }
00968     }
00969     
00970     /* cursor first */
00971     if(cu->editfont) {
00972         float si, co;
00973         
00974         ct= chartransdata+cu->pos;
00975         si= (float)sin(ct->rot);
00976         co= (float)cos(ct->rot);
00977                 
00978         f= cu->editfont->textcurs[0];
00979         
00980         f[0]= cu->fsize*(-0.1f*co + ct->xof);
00981         f[1]= cu->fsize*(0.1f*si + ct->yof);
00982         
00983         f[2]= cu->fsize*(0.1f*co + ct->xof);
00984         f[3]= cu->fsize*(-0.1f*si + ct->yof);
00985         
00986         f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
00987         f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
00988         
00989         f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
00990         f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
00991         
00992     }
00993 
00994     MEM_freeN(linedata);
00995     MEM_freeN(linedata2);       
00996     MEM_freeN(linedata3);
00997     MEM_freeN(linedata4);
00998 
00999     if (mode == FO_SELCHANGE) {
01000         MEM_freeN(chartransdata);
01001         MEM_freeN(mem);
01002         return NULL;
01003     }
01004 
01005     if(mode == FO_EDIT) {
01006         /* make nurbdata */
01007         freeNurblist(&cu->nurb);
01008         
01009         ct= chartransdata;
01010         if (cu->sepchar==0) {
01011             for (i= 0; i<slen; i++) {
01012                 unsigned long cha = (uintptr_t) mem[i];
01013                 info = &(custrinfo[i]);
01014                 if (info->mat_nr > (ob->totcol)) {
01015                     /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
01016                     info->mat_nr = 0;
01017                 }
01018                 // We do not want to see any character for \n or \r
01019                 if(cha != '\n' && cha != '\r')
01020                     buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i);
01021                 
01022                 if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
01023                     float ulwidth, uloverlap= 0.0f;
01024                     
01025                     if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
01026                          ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0)
01027                          ) {
01028                         uloverlap = xtrax + 0.1f;
01029                     }
01030                     // Find the character, the characters has to be in the memory already 
01031                     // since character checking has been done earlier already.
01032                     che= find_vfont_char(vfd, cha);
01033 
01034                     twidth = char_width(cu, che, info);
01035                     ulwidth = cu->fsize * ((twidth* (1.0f+(info->kern/40.0f)))+uloverlap);
01036                     build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize,
01037                                     ct->xof*cu->fsize + ulwidth, 
01038                                     ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize - cu->ulheight*cu->fsize,
01039                                     i, info->mat_nr);
01040                 }
01041                 ct++;
01042             }
01043         }
01044         else {
01045             int outta = 0;
01046             for (i= 0; (i<slen) && (outta==0); i++) {
01047                 ascii = mem[i];
01048                 info = &(custrinfo[i]);
01049                 if (cu->sepchar == (i+1)) {
01050                     float vecyo[3];
01051 
01052                     vecyo[0]= ct->xof;
01053                     vecyo[1]= ct->yof;
01054                     vecyo[2]= 0.0f;
01055 
01056                     mem[0] = ascii;
01057                     mem[1] = 0;
01058                     custrinfo[0]= *info;
01059                     cu->pos = 1;
01060                     cu->len = 1;
01061                     mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
01062                     outta = 1;
01063                     cu->sepchar = 0;
01064                 }
01065                 ct++;
01066             }
01067         }
01068     }
01069 
01070     if(mode==FO_DUPLI) {
01071         MEM_freeN(mem);
01072         return chartransdata;
01073     }
01074 
01075     if(mem)
01076         MEM_freeN(mem);
01077 
01078     MEM_freeN(chartransdata);
01079     return NULL;
01080 }