Added a 3D font loader that uses the Freetype2 library to
[blender.git] / source / blender / blenkernel / intern / font.c
1
2 /*  font.c     
3  *  
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <math.h>
39 #include <stdlib.h>
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45 #ifdef WIN32
46 #include "BLI_winstuff.h"
47 #endif
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_arithb.h"
51 #include "BLI_blenlib.h"
52 #include "BLI_vfontdata.h"
53
54 #include "DNA_packedFile_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_view3d_types.h"
59 #include "DNA_vfont_types.h"
60 #include "DNA_scene_types.h"
61
62 #include "BKE_utildefines.h"
63 #include "BKE_bad_level_calls.h"
64
65 #include "BKE_packedFile.h"
66
67 #include "BKE_library.h"
68 #include "BKE_font.h"
69 #include "BKE_global.h"
70 #include "BKE_main.h"
71 #include "BKE_screen.h"
72 #include "BKE_anim.h"
73 #include "BKE_curve.h"
74 #include "BKE_displist.h"
75
76
77 struct chartrans {
78         float xof, yof;
79         float rot;
80         short linenr,charnr;
81 };
82
83 void free_vfont(struct VFont *vf)
84 {
85         int i;
86
87         if (vf == 0) return;
88
89         if (vf->data) {
90                 for (i = 0; i < MAX_VF_CHARS; i++){
91                         while (vf->data->nurbsbase[i].first) {
92                                 Nurb *nu = vf->data->nurbsbase[i].first;
93                                 if (nu->bezt) MEM_freeN(nu->bezt);
94                                 BLI_freelinkN(&vf->data->nurbsbase[i], nu);
95                         }
96                 }
97
98                 MEM_freeN(vf->data);
99                 vf->data = NULL;
100         }
101         
102         if (vf->packedfile) {
103                 freePackedFile(vf->packedfile);
104                 vf->packedfile = NULL;
105         }
106 }
107
108 static void *builtin_font_data= NULL;
109 static int builtin_font_size= 0;
110
111 void BKE_font_register_builtin(void *mem, int size)
112 {
113         builtin_font_data= mem;
114         builtin_font_size= size;
115 }
116
117 static PackedFile *get_builtin_packedfile(void)
118 {
119         if (!builtin_font_data) {
120                 printf("Internal error, builtin font not loaded");
121
122                 return NULL;
123         } else {
124                 void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin");
125
126                 memcpy(mem, builtin_font_data, builtin_font_size);
127         
128                 return newPackedFileMemory(mem, builtin_font_size);
129         }
130 }
131
132 static VFontData *vfont_get_data(VFont *vfont)
133 {
134         if (!vfont->data) {
135                 PackedFile *pf;
136                 
137                 if (BLI_streq(vfont->name, "<builtin>")) {
138                         pf= get_builtin_packedfile();
139                 } else {
140                         if (vfont->packedfile) {
141                                 pf= vfont->packedfile;
142                         } else {
143                                 pf= newPackedFile(vfont->name);
144                         }
145                 }
146                 
147                 if (pf) {
148 #ifdef WITH_FREETYPE2
149                         vfont->data= BLI_vfontdata_from_freetypefont(pf);
150 #else
151                         vfont->data= BLI_vfontdata_from_psfont(pf);
152 #endif                  
153                         if (pf != vfont->packedfile) {
154                                 freePackedFile(pf);
155                         }
156                 }
157         }
158         
159         return vfont->data;     
160 }
161
162 VFont *load_vfont(char *name)
163 {
164         char filename[FILE_MAXFILE];
165         VFont *vfont= NULL;
166         PackedFile *pf;
167         int is_builtin;
168         
169         if (BLI_streq(name, "<builtin>")) {
170                 strcpy(filename, name);
171                 
172                 pf= get_builtin_packedfile();
173                 is_builtin= 1;
174         } else {
175                 char dir[FILE_MAXDIR];
176                 
177                 strcpy(dir, name);
178                 BLI_splitdirstring(dir, filename);
179
180                 pf= newPackedFile(name);
181                 is_builtin= 0;
182         }
183
184         if (pf) {
185                 VFontData *vfd;
186                 
187                 waitcursor(1);
188
189 #ifdef WITH_FREETYPE2
190                 vfd= BLI_vfontdata_from_freetypefont(pf);
191 #else
192                 vfd= BLI_vfontdata_from_psfont(pf);
193 #endif                  
194                 
195                 if (vfd) {
196                         vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
197                         vfont->data = vfd;
198                         
199                         BLI_strncpy(vfont->name, name, sizeof(vfont->name));
200
201                         // if autopack is on store the packedfile in de font structure
202                         if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
203                                 vfont->packedfile = pf;
204                         }
205                 }
206                 if (!vfont || vfont->packedfile != pf) {
207                         freePackedFile(pf);
208                 }
209         
210                 waitcursor(0);
211         }
212         
213         return vfont;
214 }
215
216 static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, float rot)
217 {
218         BezTriple *bezt1, *bezt2;
219         Nurb *nu1, *nu2;
220         float *fp, fsize, shear, x, si, co;
221         VFontData *vfd;
222         int i;
223
224         vfd= vfont_get_data(cu->vfont); 
225         if (!vfd) return;
226         
227         /* make a copy at distance ofsx,ofsy with shear*/
228         fsize= cu->fsize;
229         shear= cu->shear;
230         si= (float)sin(rot);
231         co= (float)cos(rot);
232
233         nu1 = vfd->nurbsbase[ascii].first;
234         while(nu1)
235         {
236                 bezt1 = nu1->bezt;
237                 if (bezt1){
238                         nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb");
239                         if (nu2 == 0) break;
240                         memcpy(nu2, nu1, sizeof(struct Nurb));
241                         nu2->resolu= cu->resolu;
242                         nu2->bp = 0;
243                         nu2->knotsu = nu2->knotsv = 0;
244                         nu2->flag= ME_SMOOTH;
245                         /* nu2->trim.first = 0; */
246                         /* nu2->trim.last = 0; */
247                         i = nu2->pntsu;
248
249                         bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2"); 
250                         if (bezt2 == 0){
251                                 MEM_freeN(nu2);
252                                 break;
253                         }
254                         memcpy(bezt2, bezt1, i * sizeof(struct BezTriple));
255                         nu2->bezt = bezt2;
256                         
257                         if (shear != 0.0) {
258                                 bezt2 = nu2->bezt;
259                                 
260                                 for (i= nu2->pntsu; i > 0; i--) {
261                                         bezt2->vec[0][0] += shear * bezt2->vec[0][1];
262                                         bezt2->vec[1][0] += shear * bezt2->vec[1][1];
263                                         bezt2->vec[2][0] += shear * bezt2->vec[2][1];
264                                         bezt2++;
265                                 }
266                         }
267                         if(rot!=0.0) {
268                                 bezt2= nu2->bezt;
269                                 for (i=nu2->pntsu; i > 0; i--) {
270                                         fp= bezt2->vec[0];
271                                         
272                                         x= fp[0];
273                                         fp[0]= co*x + si*fp[1];
274                                         fp[1]= -si*x + co*fp[1];
275                                         x= fp[3];
276                                         fp[3]= co*x + si*fp[4];
277                                         fp[4]= -si*x + co*fp[4];
278                                         x= fp[6];
279                                         fp[6]= co*x + si*fp[7];
280                                         fp[7]= -si*x + co*fp[7];
281
282                                         bezt2++;
283                                 }
284                         }
285                         bezt2 = nu2->bezt;
286                         
287                         for (i= nu2->pntsu; i > 0; i--) {
288                                 fp= bezt2->vec[0];
289
290                                 fp[0]= (fp[0]+ofsx)*fsize;
291                                 fp[1]= (fp[1]+ofsy)*fsize;
292                                 fp[3]= (fp[3]+ofsx)*fsize;
293                                 fp[4]= (fp[4]+ofsy)*fsize;
294                                 fp[6]= (fp[6]+ofsx)*fsize;
295                                 fp[7]= (fp[7]+ofsy)*fsize;
296                                 bezt2++;
297                         }
298                         
299                         BLI_addtail(&(cu->nurb), nu2);
300                 }
301                 nu1 = nu1->next;
302         }
303 }
304
305
306 struct chartrans *text_to_curve(Object *ob, int mode) 
307 {
308         VFont *vfont;
309         VFontData *vfd;
310         Curve *cu, *cucu;
311         struct chartrans *chartransdata, *ct;
312         float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy;
313         float cmat[3][3], timeofs, si, co, sizefac;
314         float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2;
315         int i, slen, oldflag;
316         short cnr=0, lnr=0;
317         char ascii, *mem;
318
319         /* renark: do calculations including the trailing '\0' of a string
320            because the cursor can be at that location */
321
322         if(ob->type!=OB_FONT) return 0;
323
324         cu= ob->data;
325
326         vfont= cu->vfont;
327         if (vfont==0) return 0;
328         if (cu->str==0) return 0;
329
330         vfd= vfont_get_data(vfont);
331         if (!vfd) return 0;
332         
333         /* count number of lines */
334         mem= cu->str;
335         slen = strlen(mem);
336         cu->lines= 1;
337         for (i= 0; i<=slen; i++, mem++) {
338                 ascii = *mem;
339                 if(ascii== '\n' || ascii== '\r') cu->lines++;
340         }
341
342         /* calc offset and rotation of each char */
343         ct = chartransdata =
344                 (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
345         linedata= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
346         linedata2= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
347         xof= cu->xof;
348         yof= cu->yof;
349
350         xtrax= 0.5f*cu->spacing-0.5f;
351         linedist= cu->linedist;
352
353         for (i = 0 ; i<=slen ; i++) {
354                 ascii = cu->str[i];
355                 if(ascii== '\n' || ascii== '\r' || ascii==0) {
356                         ct->xof= xof;
357                         ct->yof= yof;
358                         ct->linenr= lnr;
359                         ct->charnr= cnr;
360                         
361                         /* only empty lines are allowed smaller than 1 */
362                         if( linedist<1.0) {
363                                 if(i<slen && (cu->str[i+1]=='\r' || cu->str[i+1]=='\n')) yof-= linedist;
364                                 else yof-= 1.0;
365                         }
366                         else yof-= linedist;
367                         
368                         maxlen= MAX2(maxlen, xof);
369                         linedata[lnr]= xof;
370                         linedata2[lnr]= cnr;
371                         xof= cu->xof;
372                         lnr++;
373                         cnr= 0;
374                 }
375                 else if(ascii==9) {     /* TAB */
376                         ct->xof= xof;
377                         ct->yof= yof;
378                         ct->linenr= lnr;
379                         ct->charnr= cnr++;
380
381                         tabfac= (xof-cu->xof+0.01f);
382                         tabfac= (float)(2.0*ceil(tabfac/2.0));
383                         xof= cu->xof+tabfac;
384                 }
385                 else {
386                         ct->xof= xof;
387                         ct->yof= yof;
388                         ct->linenr= lnr;
389                         ct->charnr= cnr++;
390
391                         xof += vfd->width[ascii] + xtrax;
392                 }
393                 ct++;
394         }
395
396         /* with fontsettings calc locations of characters */
397         if(cu->spacemode!=CU_LEFT && lnr>1) {
398                 ct= chartransdata;
399
400                 if(cu->spacemode==CU_RIGHT) {
401                         for(i=0;i<lnr;i++) linedata[i]= maxlen-linedata[i];
402                         for (i=0; i<=slen; i++) {
403                                 ct->xof+= linedata[ct->linenr];
404                                 ct++;
405                         }
406                 } else if(cu->spacemode==CU_MIDDLE) {
407                         for(i=0;i<lnr;i++) linedata[i]= (maxlen-linedata[i])/2;
408                         for (i=0; i<=slen; i++) {
409                                 ct->xof+= linedata[ct->linenr];
410                                 ct++;
411                         }
412                 } else if(cu->spacemode==CU_FLUSH) {
413                         for(i=0;i<lnr;i++)
414                                 if(linedata2[i]>1)
415                                         linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1);
416                         for (i=0; i<=slen; i++) {
417                                 ct->xof+= ct->charnr*linedata[ct->linenr];
418                                 ct++;
419                         }
420                 }
421         }
422         
423         /* TEXT ON CURVE */
424         if(cu->textoncurve) {
425                 cucu= cu->textoncurve->data;
426                 
427                 oldflag= cucu->flag;
428                 cucu->flag |= (CU_PATH+CU_FOLLOW);
429                 
430                 if(cucu->path==0) calc_curvepath(cu->textoncurve);
431                 if(cucu->path) {
432                         
433
434                         Mat3CpyMat4(cmat, cu->textoncurve->obmat);
435                         sizefac= Normalise(cmat[0])/cu->fsize;
436                         
437                         minx=miny= 1.0e20f;
438                         maxx=maxy= -1.0e20f;
439                         ct= chartransdata;
440                         for (i=0; i<=slen; i++, ct++) {
441                                 if(minx>ct->xof) minx= ct->xof;
442                                 if(maxx<ct->xof) maxx= ct->xof;
443                                 if(miny>ct->yof) miny= ct->yof;
444                                 if(maxy<ct->yof) maxy= ct->yof;
445                         }
446                         
447                         /* we put the x-coordinaat exact at the curve, the y is rotated */
448                         
449                         /* length correction */
450                         distfac= sizefac*cucu->path->totdist/(maxx-minx);
451                         timeofs= 0.0;
452                         
453                         if(distfac > 1.0) {
454                                 /* path longer than text: spacemode involves */
455                                 distfac= 1.0f/distfac;
456                                 
457                                 if(cu->spacemode==CU_RIGHT) {
458                                         timeofs= 1.0f-distfac;
459                                 }
460                                 else if(cu->spacemode==CU_MIDDLE) {
461                                         timeofs= (1.0f-distfac)/2.0f;
462                                 }
463                                 else if(cu->spacemode==CU_FLUSH) distfac= 1.0f;
464                                 
465                         }
466                         else distfac= 1.0;
467                         
468                         distfac/= (maxx-minx);
469                         
470                         timeofs+= distfac*cu->xof;      /* not cyclic */
471                         
472                         ct= chartransdata;
473                         for (i=0; i<=slen; i++, ct++) {
474                                 
475                                 /* rotate around centre character */
476                                 ascii = cu->str[i];
477                                 dtime= distfac*0.35f*vfd->width[ascii]; /* why not 0.5? */
478                                 dtime= distfac*0.0f*vfd->width[ascii];  /* why not 0.5? */
479                                 
480                                 ctime= timeofs + distfac*( ct->xof - minx);
481                                 CLAMP(ctime, 0.0, 1.0);
482
483                                 /* calc the right loc AND the right rot separately */
484                                 where_on_path(cu->textoncurve, ctime, vec, tvec);
485                                 where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec);
486                                 
487                                 VecMulf(vec, sizefac);
488                                 
489                                 ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));
490
491                                 si= (float)sin(ct->rot);
492                                 co= (float)cos(ct->rot);
493
494                                 yof= ct->yof;
495                                 
496                                 ct->xof= vec[0] + si*yof;
497                                 ct->yof= vec[1] + co*yof;
498                                 
499                         }
500                         cucu->flag= oldflag;
501                 }
502         }
503
504
505         if(mode==FO_CURSUP || mode==FO_CURSDOWN) {
506                 /* 2: curs up
507                    3: curs down */
508                 ct= chartransdata+cu->pos;
509                 
510                 if(mode==FO_CURSUP && ct->linenr==0);
511                 else if(mode==FO_CURSDOWN && ct->linenr==lnr);
512                 else {
513                         if(mode==FO_CURSUP) lnr= ct->linenr-1;
514                         else lnr= ct->linenr+1;
515                         cnr= ct->charnr;
516                         /* seek for char with lnr en cnr */
517                         cu->pos= 0;
518                         ct= chartransdata;
519                         for (i= 0; i<slen; i++) {
520                                 if(ct->linenr==lnr) {
521                                         if(ct->charnr==cnr) break;
522                                         if( (ct+1)->charnr==0) break;
523                                 }
524                                 else if(ct->linenr>lnr) break;
525                                 cu->pos++;
526                                 ct++;
527                         }
528                 }
529         }
530         
531         /* cursor first */
532         if(ob==G.obedit) {
533                 ct= chartransdata+cu->pos;
534                 si= (float)sin(ct->rot);
535                 co= (float)cos(ct->rot);
536                                 
537                 f= G.textcurs[0];
538                 
539                 f[0]= cu->fsize*(-0.1f*co + ct->xof);
540                 f[1]= cu->fsize*(0.1f*si + ct->yof);
541                 
542                 f[2]= cu->fsize*(0.1f*co + ct->xof);
543                 f[3]= cu->fsize*(-0.1f*si + ct->yof);
544                 
545                 f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
546                 f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
547                 
548                 f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
549                 f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
550                 
551         }
552
553         if(mode==0) {
554                 /* make nurbdata */
555                 
556                 freeNurblist(&cu->nurb);
557                 
558                 ct= chartransdata;
559                 for (i= 0; i<slen; i++) {
560                         ascii = cu->str[i];
561                         buildchar(cu, ascii, ct->xof, ct->yof, ct->rot);
562                         ct++;
563                 }
564         }
565
566         MEM_freeN(linedata);
567         MEM_freeN(linedata2);
568
569         if(mode==FO_DUPLI) {
570                 return chartransdata;
571         }
572
573         MEM_freeN(chartransdata);
574         return 0;
575 }
576
577
578 /* ***************** DUPLI  ***************** */
579
580 static Object *find_family_object(Object **obar, char *family, char ch)
581 {
582         Object *ob;
583         int flen;
584         
585         if( obar[ch] ) return obar[ch];
586         
587         flen= strlen(family);
588         
589         ob= G.main->object.first;
590         while(ob) {
591                 if( ob->id.name[flen+2]==ch ) {
592                         if( strncmp(ob->id.name+2, family, flen)==0 ) break;
593                 }
594                 ob= ob->id.next;
595         }
596         
597         obar[ch]= ob;
598         
599         return ob;
600 }
601
602
603 void font_duplilist(Object *par)
604 {
605         extern ListBase duplilist;
606         Object *ob, *newob, *obar[256];
607         Curve *cu;
608         struct chartrans *ct, *chartransdata;
609         float vec[3], pmat[4][4], fsize, xof, yof;
610         int slen, a;
611         
612         Mat4CpyMat4(pmat, par->obmat);
613
614         /* in par the family name is stored, use this to find the other objects */
615
616         chartransdata= text_to_curve(par, FO_DUPLI);
617         if(chartransdata==0) return;
618         
619         memset(obar, 0, 256*4);
620         
621         cu= par->data;
622         slen= strlen(cu->str);
623         fsize= cu->fsize;
624         xof= cu->xof;
625         yof= cu->yof;
626         
627         ct= chartransdata;
628         set_displist_onlyzero(1);
629
630         for(a=0; a<slen; a++, ct++) {
631         
632                 ob= find_family_object(obar, cu->family, cu->str[a]);
633                 if(ob) {
634                         
635                         makeDispList(ob);
636                         
637                         vec[0]= fsize*(ct->xof - xof);
638                         vec[1]= fsize*(ct->yof - yof);
639                         vec[2]= 0.0;
640         
641                         Mat4MulVecfl(pmat, vec);
642                         
643                         newob= MEM_mallocN(sizeof(Object), "newobj dupli");
644                         memcpy(newob, ob, sizeof(Object));
645                         newob->flag |= OB_FROMDUPLI;
646                         newob->id.newid= (ID *)par;             /* keep duplicator */
647                         newob->totcol= par->totcol;     /* for give_current_material */
648                         
649                         Mat4CpyMat4(newob->obmat, par->obmat);
650                         VECCOPY(newob->obmat[3], vec);
651                         
652                         newob->parent= 0;
653                         newob->track= 0;
654                         
655                         BLI_addtail(&duplilist, newob);
656                 }
657                 
658         }
659         set_displist_onlyzero(0);
660         MEM_freeN(chartransdata);
661 }