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