tedious string copying changes
[blender.git] / source / blender / blenkernel / intern / font.c
index e2dccf02b40f689ee40bf9832ea83a9bc6173b1a..5fdb9549179a9e27ca8b6cf5cf6ab3d4707d6e6c 100644 (file)
@@ -1,4 +1,4 @@
-/*  font.c     
+/*  font.c
  *  
  * 
  * $Id$
@@ -17,7 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <math.h>
 #include <stdlib.h>
 #include <wchar.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include <wctype.h>
 
 #include "MEM_guardedalloc.h"
 
 
 #include "DNA_packedFile_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_object_types.h"
-#include "DNA_view3d_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 
 #include "BKE_utildefines.h"
 
@@ -60,7 +56,6 @@
 #include "BKE_font.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
-#include "BKE_screen.h"
 #include "BKE_anim.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
@@ -128,8 +123,8 @@ wcsleninu8(wchar_t *src)
        return len;
 }
 
-int
-static utf8slen(char *src)
+static int
+utf8slen(char *src)
 {
        int size = 0, index = 0;
        unsigned char c;
@@ -163,7 +158,7 @@ According to RFC 3629 "UTF-8, a transformation format of ISO 10646"
 (http://tools.ietf.org/html/rfc3629), the valid UTF-8 encoding are:
 
   Char. number range  |        UTF-8 octet sequence
-      (hexadecimal)    |              (binary)
+         (hexadecimal)    |              (binary)
    --------------------+---------------------------------------------
    0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
@@ -205,7 +200,7 @@ int utf8towchar(wchar_t *w, char *c)
                                *w = '?';
                        }
                } else
-                   *w=(c[0] & 0x7f);
+                       *w=(c[0] & 0x7f);
 
                c++;
                w++;
@@ -270,13 +265,11 @@ static PackedFile *get_builtin_packedfile(void)
 void free_ttfont(void)
 {
        struct TmpFont *tf;
-       
-       tf= ttfdata.first;
-       while(tf) {
-               freePackedFile(tf->pf);
+
+       for(tf= ttfdata.first; tf; tf= tf->next) {
+               if(tf->pf) freePackedFile(tf->pf); /* NULL when the font file can't be found on disk */
                tf->pf= NULL;
                tf->vfont= NULL;
-               tf= tf->next;
        }
        BLI_freelistN(&ttfdata);
 }
@@ -312,7 +305,7 @@ static VFontData *vfont_get_data(VFont *vfont)
        if (!vfont->data) {
                PackedFile *pf;
                
-               if (BLI_streq(vfont->name, "<builtin>")) {
+               if (strcmp(vfont->name, FO_BUILTIN_NAME)==0) {
                        pf= get_builtin_packedfile();
                } else {
                        if (vfont->packedfile) {
@@ -349,7 +342,7 @@ static VFontData *vfont_get_data(VFont *vfont)
                        if(!pf) {
                                printf("Font file doesn't exist: %s\n", vfont->name);
 
-                               strcpy(vfont->name, "<builtin>");
+                               strcpy(vfont->name, FO_BUILTIN_NAME);
                                pf= get_builtin_packedfile();
                        }
                }
@@ -374,7 +367,7 @@ VFont *load_vfont(char *name)
        int is_builtin;
        struct TmpFont *tmpfnt;
        
-       if (BLI_streq(name, "<builtin>")) {
+       if (strcmp(name, FO_BUILTIN_NAME)==0) {
                strcpy(filename, name);
                
                pf= get_builtin_packedfile();
@@ -398,7 +391,11 @@ VFont *load_vfont(char *name)
                if (vfd) {
                        vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
                        vfont->data = vfd;
-                       
+
+                       /* if there's a font name, use it for the ID name */
+                       if (strcmp(vfd->name, "")!=0) {
+                               BLI_strncpy(vfont->id.name+2, vfd->name, sizeof(vfont->id.name)-2);
+                       }
                        BLI_strncpy(vfont->name, name, sizeof(vfont->name));
 
                        // if autopack is on store the packedfile in de font structure
@@ -406,8 +403,8 @@ VFont *load_vfont(char *name)
                                vfont->packedfile = pf;
                        }
                        
-                       // Do not add <builtin> to temporary listbase
-                       if(strcmp(filename, "<builtin>"))
+                       // Do not add FO_BUILTIN_NAME to temporary listbase
+                       if(strcmp(filename, FO_BUILTIN_NAME))
                        {
                                tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
                                tmpfnt->pf= tpf;
@@ -429,12 +426,12 @@ VFont *load_vfont(char *name)
 
 static VFont *which_vfont(Curve *cu, CharInfo *info)
 {
-       switch(info->flag & CU_STYLE) {
-               case CU_BOLD:
+       switch(info->flag & (CU_CHINFO_BOLD|CU_CHINFO_ITALIC)) {
+               case CU_CHINFO_BOLD:
                        if (cu->vfontb) return(cu->vfontb); else return(cu->vfont);
-               case CU_ITALIC:
+               case CU_CHINFO_ITALIC:
                        if (cu->vfonti) return(cu->vfonti); else return(cu->vfont);
-               case (CU_BOLD|CU_ITALIC):
+               case (CU_CHINFO_BOLD|CU_CHINFO_ITALIC):
                        if (cu->vfontbi) return(cu->vfontbi); else return(cu->vfont);
                default:
                        return(cu->vfont);
@@ -446,12 +443,23 @@ VFont *get_builtin_font(void)
        VFont *vf;
        
        for (vf= G.main->vfont.first; vf; vf= vf->id.next)
-               if (BLI_streq(vf->name, "<builtin>"))
+               if (strcmp(vf->name, FO_BUILTIN_NAME)==0)
                        return vf;
        
-       return load_vfont("<builtin>");
+       return load_vfont(FO_BUILTIN_NAME);
 }
 
+static VChar *find_vfont_char(VFontData *vfd, intptr_t character)
+{
+       VChar *che= NULL;
+
+       for(che = vfd->characters.first; che; che = che->next) {
+               if(che->index == character)
+                       break;
+       }
+       return che; /* NULL if not found */
+}
+               
 static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr)
 {
        Nurb *nu2;
@@ -469,7 +477,7 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
        nu2->pntsv = 1;
        nu2->orderu = 4;
        nu2->orderv = 1;
-       nu2->flagu = CU_CYCLIC;
+       nu2->flagu = CU_NURB_CYCLIC;
 
        bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); 
        if (bp == 0){
@@ -506,11 +514,12 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
        float *fp, fsize, shear, x, si, co;
        VFontData *vfd = NULL;
        VChar *che = NULL;
-       int i, sel=0;
+       int i;
 
        vfd= vfont_get_data(which_vfont(cu, info));     
        if (!vfd) return;
 
+       /*
        if (cu->selend < cu->selstart) {
                if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
                        sel= 1;
@@ -519,6 +528,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
                if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
                        sel= 1;
        }
+       */
 
        /* make a copy at distance ofsx,ofsy with shear*/
        fsize= cu->fsize;
@@ -526,14 +536,7 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
        si= (float)sin(rot);
        co= (float)cos(rot);
 
-       // Find the correct character from the font
-       che = vfd->characters.first;
-       while(che)
-       {
-               if(che->index == character)
-                       break;
-               che = che->next;
-       }
+       che= find_vfont_char(vfd, character);
        
        // Select the glyph data
        if(che)
@@ -600,9 +603,23 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float
                        }
                        bezt2 = nu2->bezt;
 
+                       if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
+                               const float sca= cu->smallcaps_scale;
+                               for (i= nu2->pntsu; i > 0; i--) {
+                                       fp= bezt2->vec[0];
+                                       fp[0] *= sca;
+                                       fp[1] *= sca;
+                                       fp[3] *= sca;
+                                       fp[4] *= sca;
+                                       fp[6] *= sca;
+                                       fp[7] *= sca;
+                                       bezt2++;
+                               }
+                       }
+                       bezt2 = nu2->bezt;
+
                        for (i= nu2->pntsu; i > 0; i--) {
                                fp= bezt2->vec[0];
-
                                fp[0]= (fp[0]+ofsx)*fsize;
                                fp[1]= (fp[1]+ofsy)*fsize;
                                fp[3]= (fp[3]+ofsx)*fsize;
@@ -638,6 +655,20 @@ int BKE_font_getselection(Object *ob, int *start, int *end)
        }
 }
 
+static float char_width(Curve *cu, VChar *che, CharInfo *info)
+{
+       // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
+       if(che == NULL) {
+               return 0.0f;
+       }
+       else if(info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
+               return che->width * cu->smallcaps_scale;
+       }
+       else {
+               return che->width;
+       }
+}
+
 struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) 
 {
        VFont *vfont, *oldvfont;
@@ -705,10 +736,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
 
        /* We assume the worst case: 1 character per line (is freed at end anyway) */
 
-       linedata= MEM_mallocN(sizeof(float)*(slen+2),"buildtext2");
-       linedata2= MEM_mallocN(sizeof(float)*(slen+2),"buildtext3");
-       linedata3= MEM_callocN(sizeof(float)*(slen+2),"buildtext4");    
-       linedata4= MEM_callocN(sizeof(float)*(slen+2),"buildtext5");            
+       linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
+       linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
+       linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");        
+       linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");                
        
        linedist= cu->linedist;
        
@@ -719,7 +750,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
 
        oldvfont = NULL;
 
-       for (i=0; i<slen; i++) custrinfo[i].flag &= ~CU_WRAP;
+       for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK);
 
        if (cu->selboxes) MEM_freeN(cu->selboxes);
        cu->selboxes = NULL;
@@ -732,35 +763,33 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
        makebreak:
                // Characters in the list
                che = vfd->characters.first;
-               ascii = mem[i];
                info = &(custrinfo[i]);
+               ascii = mem[i];
+               if(info->flag & CU_CHINFO_SMALLCAPS) {
+                       ascii = towupper(ascii);
+                       if(mem[i] != ascii) {
+                               mem[i]= ascii;
+                               info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
+                       }
+               }
+
                vfont = which_vfont(cu, info);
                
                if(vfont==NULL) break;
-               
-               // Find the character
-               while(che) {
-                       if(che->index == ascii)
-                               break;
-                       che = che->next;
-               }
+
+               che= find_vfont_char(vfd, ascii);
 
                /*
                 * The character wasn't in the current curve base so load it
-                * But if the font is <builtin> then do not try loading since
+                * But if the font is FO_BUILTIN_NAME then do not try loading since
                 * whole font is in the memory already
                 */
-               if(che == NULL && strcmp(vfont->name, "<builtin>"))     {
+               if(che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) {
                        BLI_vfontchar_from_freetypefont(vfont, ascii);
                }
 
                /* Try getting the character again from the list */
-               che = vfd->characters.first;
-               while(che) {
-                       if(che->index == ascii)
-                               break;
-                       che = che->next;
-               }
+               che= find_vfont_char(vfd, ascii);
 
                /* No VFont found */
                if (vfont==0) {
@@ -783,14 +812,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                        return 0;
                }
 
-               // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
-               if(!che)
-                       twidth = 0;
-               else
-                       twidth = che->width;
+               twidth = char_width(cu, che, info);
 
                // Calculate positions
-               if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) {
+               if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) {
        //              fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
                        for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
                                if (mem[j]==' ' || mem[j]=='-') {
@@ -801,13 +826,13 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                                        i = j-1;
                                        xof = ct->xof;
                                        ct[1].dobreak = 1;
-                                       custrinfo[i+1].flag |= CU_WRAP;
+                                       custrinfo[i+1].flag |= CU_CHINFO_WRAP;
                                        goto makebreak;
                                }
                                if (chartransdata[j].dobreak) {
        //                              fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
                                        ct->dobreak= 1;
-                                       custrinfo[i+1].flag |= CU_WRAP;
+                                       custrinfo[i+1].flag |= CU_CHINFO_WRAP;
                                        ct -= 1;
                                        cnr -= 1;
                                        i--;
@@ -831,8 +856,8 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                        linedata4[lnr]= wsnr;
                        
                        if ( (tb->h != 0.0) &&
-                            ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize))) &&
-                            (cu->totbox > (curbox+1)) ) {
+                                ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) &&
+                                (cu->totbox > (curbox+1)) ) {
                                maxlen= 0;
                                tb++;
                                curbox++;
@@ -884,10 +909,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                        else wsfac = 1.0;
                        
                        // Set the width of the character
-                       if(!che)
-                               twidth = 0;
-                       else 
-                               twidth = che->width;
+                       twidth = char_width(cu, che, info);
 
                        xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
                        
@@ -926,13 +948,13 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                                ct++;
                        }
                } else if((cu->spacemode==CU_FLUSH) &&
-                         (cu->tb[0].w != 0.0)) {
+                                 (cu->tb[0].w != 0.0)) {
                        for(i=0;i<lnr;i++)
                                if(linedata2[i]>1)
                                        linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
                        for (i=0; i<=slen; i++) {
                                for (j=i; (mem[j]) && (mem[j]!='\n') && 
-                                         (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+                                                 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
 //                             if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
                                        ct->xof+= ct->charnr*linedata[ct->linenr];
 //                             }
@@ -943,10 +965,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                        float curofs= 0.0f;
                        for (i=0; i<=slen; i++) {
                                for (j=i; (mem[j]) && (mem[j]!='\n') && 
-                                         (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+                                                 (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
                                if ((mem[j]!='\r') && (mem[j]!='\n') &&
-                                   ((chartransdata[j].dobreak!=0))) {
-                                   if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
+                                       ((chartransdata[j].dobreak!=0))) {
+                                       if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
                                        ct->xof+= curofs;
                                }
                                if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
@@ -956,7 +978,8 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
        }
        
        /* TEXT ON CURVE */
-       if(cu->textoncurve) {
+       /* Note: Only OB_CURVE objects could have a path  */
+       if(cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
                Curve *cucu= cu->textoncurve->data;
                int oldflag= cucu->flag;
                
@@ -1017,19 +1040,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                                
                                /* rotate around center character */
                                ascii = mem[i];
-                               
-                               // Find the character
-                               che = vfd->characters.first;
-                               while(che) {
-                                       if(che->index == ascii)
-                                               break;
-                                       che = che->next;
-                               }
+
+                               che= find_vfont_char(vfd, ascii);
        
-                               if(che)
-                                       twidth = che->width;
-                               else
-                                       twidth = 0;
+                               twidth = char_width(cu, che, info);
                                
                                dtime= distfac*0.35f*twidth;    /* why not 0.5? */
                                dtime= distfac*0.5f*twidth;     /* why not 0.5? */
@@ -1039,8 +1053,8 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
 
                                /* calc the right loc AND the right rot separately */
                                /* vec, tvec need 4 items */
-                               where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL);
-                               where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL);
+                               where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
+                               where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL);
                                
                                mul_v3_fl(vec, sizefac);
                                
@@ -1134,16 +1148,14 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                return NULL;
        }
 
-       if(mode==0) {
+       if(mode == FO_EDIT) {
                /* make nurbdata */
-               unsigned long cha;
-               
                freeNurblist(&cu->nurb);
                
                ct= chartransdata;
                if (cu->sepchar==0) {
                        for (i= 0; i<slen; i++) {
-                               cha = (uintptr_t) mem[i];
+                               unsigned long cha = (uintptr_t) mem[i];
                                info = &(custrinfo[i]);
                                if (info->mat_nr > (ob->totcol)) {
                                        /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
@@ -1153,24 +1165,19 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                                if(cha != '\n' && cha != '\r')
                                        buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i);
                                
-                               if ((info->flag & CU_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
+                               if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
                                        float ulwidth, uloverlap= 0.0f;
                                        
                                        if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
-                                                ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_UNDERLINE)) && ((custrinfo[i+1].flag & CU_WRAP)==0)
+                                                ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0)
                                                 ) {
                                                uloverlap = xtrax + 0.1;
                                        }
                                        // Find the character, the characters has to be in the memory already 
                                        // since character checking has been done earlier already.
-                                       che = vfd->characters.first;
-                                       while(che) {
-                                               if(che->index == cha)
-                                                       break;
-                                               che = che->next;
-                                       }
-                                       
-                                       if(!che) twidth =0; else twidth=che->width;
+                                       che= find_vfont_char(vfd, cha);
+
+                                       twidth = char_width(cu, che, info);
                                        ulwidth = cu->fsize * ((twidth* (1.0+(info->kern/40.0)))+uloverlap);
                                        build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize, 
                                                                        ct->xof*cu->fsize + ulwidth, 
@@ -1187,17 +1194,17 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                                info = &(custrinfo[i]);
                                if (cu->sepchar == (i+1)) {
                                        float vecyo[3];
-                                       
+
+                                       vecyo[0]= ct->xof;
+                                       vecyo[1]= ct->yof;
+                                       vecyo[2]= 0.0f;
+
                                        mem[0] = ascii;
                                        mem[1] = 0;
                                        custrinfo[0]= *info;
                                        cu->pos = 1;
                                        cu->len = 1;
-                                       vecyo[0] = ct->xof;
-                                       vecyo[1] = ct->yof;
-                                       vecyo[2] = 0;
-                                       mul_m4_v3(ob->obmat, vecyo);
-                                       VECCOPY(ob->loc, vecyo);
+                                       mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
                                        outta = 1;
                                        cu->sepchar = 0;
                                }