Blender V2.61 - r43446
|
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 }