Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_font.h4
-rw-r--r--source/blender/blenkernel/BKE_global.h5
-rw-r--r--source/blender/blenkernel/intern/blender.c4
-rw-r--r--source/blender/blenkernel/intern/font.c417
-rw-r--r--source/blender/blenlib/BLI_vfontdata.h34
-rw-r--r--source/blender/blenlib/intern/freetypefont.c496
-rw-r--r--source/blender/blenlib/intern/psfont.c8
-rw-r--r--source/blender/blenloader/intern/writefile.c9
-rw-r--r--source/blender/include/BIF_editfont.h16
-rw-r--r--source/blender/include/BIF_interface.h1
-rw-r--r--source/blender/include/butspace.h6
-rw-r--r--source/blender/src/buttons_editing.c306
-rw-r--r--source/blender/src/editfont.c222
-rw-r--r--source/blender/src/interface.c117
-rw-r--r--source/blender/src/interface_draw.c136
-rw-r--r--source/blender/src/usiblender.c24
16 files changed, 1511 insertions, 294 deletions
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index ab0fcf6b994..fbc0d70fa22 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -56,6 +56,10 @@ int mat_to_sel(void);
void font_duplilist(struct Object *par);
int getselection(int *start, int *end);
+void chtoutf8(unsigned long c, char *o);
+void wcs2utf8s(char *dst, wchar_t *src);
+int wcsleninu8(wchar_t *src);
+int utf8towchar_(wchar_t *w, char *c);
#endif
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 5ea8b398363..2335510ac2d 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -117,6 +117,11 @@ typedef struct Global {
/* Rob's variables */
int have_quicktime;
int ui_international;
+ int charstart;
+ int charmin;
+ int charmax;
+ struct VFont *selfont;
+ struct ListBase ttfdata;
/* this variable is written to / read from FileGlobal->fileflags */
int fileflags;
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index b08b99a4010..2fca941a651 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -217,6 +217,10 @@ void initglobals(void)
#endif
clear_workob(); /* object.c */
+
+ G.charstart = 0x0000;
+ G.charmin = 0x0000;
+ G.charmax = 0xffff;
}
/***/
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index af7a94e079e..500fed8831a 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -37,6 +37,7 @@
#include <string.h>
#include <math.h>
#include <stdlib.h>
+#include <wchar.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -80,19 +81,151 @@ struct chartrans {
char dobreak;
};
-void free_vfont(struct VFont *vf)
+/* UTF-8 <-> wchar transformations */
+void
+chtoutf8(unsigned long c, char *o)
+{
+ // Variables and initialization
+ memset(o, 0, 16);
+
+ // Create the utf-8 string
+ if (c < 0x80)
+ {
+ o[0] = (char) c;
+ }
+ else if (c < 0x800)
+ {
+ o[0] = (0xC0 | (c>>6));
+ o[1] = (0x80 | (c & 0x3f));
+ }
+ else if (c < 0x10000)
+ {
+ o[0] = (0xe0 | (c >> 12));
+ o[1] = (0x80 | (c >>6 & 0x3f));
+ o[2] = (0x80 | (c & 0x3f));
+ }
+ else if (c < 0x200000)
+ {
+ o[0] = (0xf0 | (c>>18));
+ o[1] = (0x80 | (c >>12 & 0x3f));
+ o[2] = (0x80 | (c >> 6 & 0x3f));
+ o[3] = (0x80 | (c & 0x3f));
+ }
+}
+
+void
+wcs2utf8s(char *dst, wchar_t *src)
{
- int i;
+ char ch[5];
+ while(*src)
+ {
+ memset(ch, 0, 5);
+ chtoutf8(*src++, ch);
+ strcat(dst, ch);
+ }
+}
+
+int
+wcsleninu8(wchar_t *src)
+{
+ char ch[16];
+ int len = 0;
+
+ while(*src)
+ {
+ memset(ch, 0, 16);
+ chtoutf8(*src++, ch);
+ len = len + strlen(ch);
+ }
+
+ return len;
+}
+
+int
+utf8slen(char *src)
+{
+ int size = 0, index = 0;
+ unsigned char c;
+
+ c = src[index++];
+ while(c)
+ {
+ if((c & 0x80) == 0)
+ {
+ index += 0;
+ }
+ else if((c & 0xe0) == 0xe0)
+ {
+ index += 2;
+ }
+ else
+ {
+ index += 1;
+ }
+ size += 1;
+ c = src[index++];
+ }
+
+ return size;
+}
+
+int utf8towchar_(wchar_t *w, char *c)
+{
+ int len=0;
+ if(w==NULL || c==NULL) return(0);
+ //printf("%s\n",c);
+ while(*c)
+ {
+ if(*c & 0x80)
+ {
+ if(*c & 0x40)
+ {
+ if(*c & 0x20)
+ {
+ if(*c & 0x10)
+ {
+ *w=(c[0] & 0x0f)<<18 | (c[1]&0x1f)<<12 | (c[2]&0x3f)<<6 | (c[3]&0x7f);
+ c++;
+ }
+ else
+ *w=(c[0] & 0x1f)<<12 | (c[1]&0x3f)<<6 | (c[2]&0x7f);
+ c++;
+ }
+ else
+ *w=(((c[0] &0x3f)<<6) | (c[1]&0x7f));
+ c++;
+ }
+ else
+ *w=(c[0] & 0x7f);
+ }
+ else
+ *w=(c[0] & 0x7f);
+
+ c++;
+ w++;
+ len++;
+ }
+ return len;
+}
+
+/* The vfont code */
+void free_vfont(struct VFont *vf)
+{
if (vf == 0) return;
if (vf->data) {
- for (i = 0; i < MAX_VF_CHARS; i++){
- while (vf->data->nurbsbase[i].first) {
- Nurb *nu = vf->data->nurbsbase[i].first;
+ while(vf->data->characters.first)
+ {
+ VChar *che = vf->data->characters.first;
+
+ while (che->nurbsbase.first) {
+ Nurb *nu = che->nurbsbase.first;
if (nu->bezt) MEM_freeN(nu->bezt);
- BLI_freelinkN(&vf->data->nurbsbase[i], nu);
+ BLI_freelinkN(&che->nurbsbase, nu);
}
+
+ BLI_freelinkN(&vf->data->characters, che);
}
MEM_freeN(vf->data);
@@ -131,6 +264,20 @@ static PackedFile *get_builtin_packedfile(void)
static VFontData *vfont_get_data(VFont *vfont)
{
+ struct TmpFont *tmpfnt = NULL;
+ PackedFile *tpf;
+
+ // Try finding the font from font list
+ tmpfnt = G.ttfdata.first;
+
+ while(tmpfnt)
+ {
+ if(tmpfnt->vfont == vfont)
+ break;
+ tmpfnt = tmpfnt->next;
+ }
+
+ // And then set the data
if (!vfont->data) {
PackedFile *pf;
@@ -139,8 +286,34 @@ static VFontData *vfont_get_data(VFont *vfont)
} else {
if (vfont->packedfile) {
pf= vfont->packedfile;
+
+ // We need to copy a tmp font to memory unless it is already there
+ if(!tmpfnt)
+ {
+ tpf= MEM_callocN(sizeof(*tpf), "PackedFile");
+ tpf->data= MEM_mallocN(pf->size, "packFile");
+ tpf->size= pf->size;
+ memcpy(tpf->data, pf->data, pf->size);
+
+ // Add temporary packed file to globals
+ tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
+ tmpfnt->pf= tpf;
+ tmpfnt->vfont= vfont;
+ BLI_addtail(&G.ttfdata, tmpfnt);
+ }
} else {
pf= newPackedFile(vfont->name);
+
+ if(!tmpfnt)
+ {
+ tpf= newPackedFile(vfont->name);
+
+ // Add temporary packed file to globals
+ tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
+ tmpfnt->pf= tpf;
+ tmpfnt->vfont= vfont;
+ BLI_addtail(&G.ttfdata, tmpfnt);
+ }
}
if(!pf) {
printf("Font file doesn't exist: %s\n", vfont->name);
@@ -170,7 +343,9 @@ VFont *load_vfont(char *name)
char filename[FILE_MAXFILE];
VFont *vfont= NULL;
PackedFile *pf;
+ PackedFile *tpf = NULL;
int is_builtin;
+ struct TmpFont *tmpfnt;
if (BLI_streq(name, "<builtin>")) {
strcpy(filename, name);
@@ -184,6 +359,8 @@ VFont *load_vfont(char *name)
BLI_splitdirstring(dir, filename);
pf= newPackedFile(name);
+ tpf= newPackedFile(name);
+
is_builtin= 0;
}
@@ -196,7 +373,7 @@ VFont *load_vfont(char *name)
vfd= BLI_vfontdata_from_freetypefont(pf);
#else
vfd= BLI_vfontdata_from_psfont(pf);
-#endif
+#endif
if (vfd) {
vfont = alloc_libblock(&G.main->vfont, ID_VF, filename);
@@ -208,7 +385,18 @@ VFont *load_vfont(char *name)
if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
vfont->packedfile = pf;
}
+
+ // Do not add <builtin> to temporary listbase
+ if(strcmp(filename, "<builtin>"))
+ {
+ tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
+ tmpfnt->pf= tpf;
+ tmpfnt->vfont= vfont;
+ BLI_addtail(&G.ttfdata, tmpfnt);
+ }
}
+
+ // Free the packed file
if (!vfont || vfont->packedfile != pf) {
freePackedFile(pf);
}
@@ -281,12 +469,13 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i
}
-static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
+static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
{
BezTriple *bezt1, *bezt2;
- Nurb *nu1, *nu2;
+ Nurb *nu1 = NULL, *nu2 = NULL;
float *fp, fsize, shear, x, si, co;
- VFontData *vfd;
+ VFontData *vfd = NULL;
+ VChar *che = NULL;
int i, sel=0;
vfd= vfont_get_data(which_vfont(cu, info));
@@ -307,7 +496,20 @@ static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx
si= (float)sin(rot);
co= (float)cos(rot);
- nu1 = vfd->nurbsbase[ascii].first;
+ // Find the correct character from the font
+ che = vfd->characters.first;
+ while(che)
+ {
+ if(che->index == character)
+ break;
+ che = che->next;
+ }
+
+ // Select the glyph data
+ if(che)
+ nu1 = che->nurbsbase.first;
+
+ // Create the character
while(nu1)
{
bezt1 = nu1->bezt;
@@ -419,7 +621,7 @@ struct chartrans *text_to_curve(Object *ob, int mode)
float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
int i, slen, oldflag, j;
short cnr=0, lnr=0, wsnr= 0;
- char ascii, *mem;
+ wchar_t *mem, *tmp, ascii;
int outta;
float vecyo[3], curofs;
CharInfo *info;
@@ -429,22 +631,39 @@ struct chartrans *text_to_curve(Object *ob, int mode)
int curbox;
int selstart, selend;
SelBox *sb= NULL; /* to please gcc */
+ VChar *che;
+ float twidth;
+ int utf8len;
/* renark: do calculations including the trailing '\0' of a string
because the cursor can be at that location */
if(ob->type!=OB_FONT) return 0;
- cu= ob->data;
- mem= cu->str;
- slen = strlen(mem);
+ // Set font data
+ cu= (Curve *) ob->data;
+ vfont= cu->vfont;
+
+ if(cu->str == 0) return 0;
+ if(vfont == 0) return 0;
+
+ // Create unicode string
+ utf8len = utf8slen(cu->str);
+ tmp = mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
+
+ utf8towchar_(mem, cu->str);
+
+ // Count the wchar_t string length
+ slen = wcslen(mem);
if (cu->ulheight == 0.0) cu->ulheight = 0.05;
- if (cu->str==0) return 0;
if (cu->strinfo==NULL) { /* old file */
cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat");
}
+ vfd= vfont_get_data(vfont);
+ if(!vfd) goto errcse;
+
/* calc offset and rotation of each char */
ct = chartransdata =
(struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
@@ -476,23 +695,65 @@ struct chartrans *text_to_curve(Object *ob, int mode)
curbox= 0;
for (i = 0 ; i<=slen ; i++) {
makebreak:
- ascii = cu->str[i];
+ // Characters in the list
+ che = vfd->characters.first;
+ ascii = mem[i];
info = &(cu->strinfo[i]);
vfont = which_vfont(cu, info);
- if (vfont==0) return 0;
+
+ // Find the character
+ while(che)
+ {
+ if(che->index == ascii)
+ break;
+ che = che->next;
+ }
+
+#ifdef WITH_FREETYPE2
+ // The character wasn't in the current curve base so load it
+ // But if the font is <builtin> then do not try loading since whole font is in the memory already
+ if(che == NULL && strcmp(vfont->name, "<builtin>"))
+ {
+ 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;
+ }
+#endif
+
+
+ if (vfont==0) goto errcse;
if (vfont != oldvfont) {
vfd= vfont_get_data(vfont);
oldvfont = vfont;
}
- if (!vfd) return 0;
- if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+vfd->width[ascii])*cu->fsize) > tb->w) {
-// fprintf(stderr, "linewidth exceeded: %c%c%c...\n", cu->str[i], cu->str[i+1], cu->str[i+2]);
- for (j=i; j && (cu->str[j] != '\n') && (cu->str[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
- if (cu->str[j]==' ' || cu->str[j]=='-') {
+ if (!vfd) goto errcse;
+
+ // The character wasn't found, propably ascii = 0, then the width shall be 0 as well
+ if(!che)
+ {
+ twidth = 0;
+ }
+ else
+ {
+ twidth = che->width;
+ }
+
+ // Calculate positions
+ if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) {
+// 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]=='-') {
ct -= (i-(j-1));
cnr -= (i-(j-1));
- if (cu->str[j] == ' ') wsnr--;
- if (cu->str[j] == '-') wsnr++;
+ if (mem[j] == ' ') wsnr--;
+ if (mem[j] == '-') wsnr++;
i = j-1;
xof = ct->xof;
ct[1].dobreak = 1;
@@ -500,7 +761,7 @@ struct chartrans *text_to_curve(Object *ob, int mode)
goto makebreak;
}
if (chartransdata[j].dobreak) {
-// fprintf(stderr, "word too long: %c%c%c...\n", cu->str[j], cu->str[j+1], cu->str[j+2]);
+// fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
ct->dobreak= 1;
cu->strinfo[i+1].flag |= CU_WRAP;
ct -= 1;
@@ -533,7 +794,12 @@ struct chartrans *text_to_curve(Object *ob, int mode)
curbox++;
yof= cu->yof + tb->y/cu->fsize;
}
-
+
+ if(ascii == '\n' || ascii == '\r')
+ xof = cu->xof;
+ else
+ xof= cu->xof + (tb->x/cu->fsize);
+
xof= cu->xof + (tb->x/cu->fsize);
lnr++;
cnr= 0;
@@ -566,7 +832,16 @@ struct chartrans *text_to_curve(Object *ob, int mode)
wsfac = cu->wordspace;
wsnr++;
} else wsfac = 1.0;
- xof += (vfd->width[ascii]*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
+ // Set the width of the character
+ if(!che)
+ {
+ twidth = 0;
+ }
+ else
+ {
+ twidth = che->width;
+ }
+ xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax;
if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w;
}
@@ -577,8 +852,9 @@ struct chartrans *text_to_curve(Object *ob, int mode)
cu->lines= 1;
ct= chartransdata;
- for (i= 0; i<=slen; i++, mem++, ct++) {
- ascii = *mem;
+ tmp = mem;
+ for (i= 0; i<=slen; i++, tmp++, ct++) {
+ ascii = *tmp;
if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
}
@@ -608,9 +884,9 @@ struct chartrans *text_to_curve(Object *ob, int mode)
if(linedata2[i]>1)
linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
for (i=0; i<=slen; i++) {
- for (j=i; (cu->str[j]) && (cu->str[j]!='\n') &&
- (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
-// if ((cu->str[j]!='\r') && (cu->str[j]!='\n') && (cu->str[j])) {
+ for (j=i; (mem[j]) && (mem[j]!='\n') &&
+ (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];
// }
ct++;
@@ -619,14 +895,14 @@ struct chartrans *text_to_curve(Object *ob, int mode)
(cu->tb[0].w != 0.0)) {
curofs= 0;
for (i=0; i<=slen; i++) {
- for (j=i; (cu->str[j]) && (cu->str[j]!='\n') &&
- (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
- if ((cu->str[j]!='\r') && (cu->str[j]!='\n') &&
+ for (j=i; (mem[j]) && (mem[j]!='\n') &&
+ (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
+ if ((mem[j]!='\r') && (mem[j]!='\n') &&
((chartransdata[j].dobreak!=0))) {
- if (cu->str[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
+ if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
ct->xof+= curofs;
}
- if (cu->str[i]=='\n' || cu->str[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
+ if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
ct++;
}
}
@@ -685,9 +961,28 @@ struct chartrans *text_to_curve(Object *ob, int mode)
for (i=0; i<=slen; i++, ct++) {
/* rotate around centre character */
- ascii = cu->str[i];
- dtime= distfac*0.35f*vfd->width[ascii]; /* why not 0.5? */
- dtime= distfac*0.0f*vfd->width[ascii]; /* why not 0.5? */
+ ascii = mem[i];
+
+ // Find the character
+ che = vfd->characters.first;
+ while(che)
+ {
+ if(che->index == ascii)
+ break;
+ che = che->next;
+ }
+
+ if(che)
+ {
+ twidth = che->width;
+ }
+ else
+ {
+ twidth = 0;
+ }
+
+ dtime= distfac*0.35f*twidth; /* why not 0.5? */
+ dtime= distfac*0.0f*twidth; /* why not 0.5? */
ctime= timeofs + distfac*( ct->xof - minx);
CLAMP(ctime, 0.0, 1.0);
@@ -782,32 +1077,47 @@ struct chartrans *text_to_curve(Object *ob, int mode)
if (mode == FO_SELCHANGE) {
MEM_freeN(chartransdata);
+ MEM_freeN(mem);
return NULL;
}
if(mode==0) {
/* make nurbdata */
-
+ unsigned long cha;
+
freeNurblist(&cu->nurb);
ct= chartransdata;
if (cu->sepchar==0) {
for (i= 0; i<slen; i++) {
- ascii = cu->str[i];
+ cha = (unsigned long) mem[i];
info = &(cu->strinfo[i]);
if (info->mat_nr > (ob->totcol)) {
printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr);
info->mat_nr = 0;
}
- buildchar(cu, ascii, info, ct->xof, ct->yof, ct->rot, i);
- if ((info->flag & CU_UNDERLINE) && (ascii != '\n') && (ascii != '\r')) {
+ // We do not want to see any character for \n or \r
+ if(cha != '\n' && cha != '\r')
+ buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i);
+ if ((info->flag & CU_UNDERLINE) && (cha != '\n') && (cha != '\r')) {
uloverlap = 0;
- if ( (i<(slen-1)) && (cu->str[i+1] != '\n') && (cu->str[i+1] != '\r') &&
- ((cu->str[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0)
+ if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
+ ((mem[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0)
) {
uloverlap = xtrax + 0.1;
}
- ulwidth = cu->fsize * ((vfd->width[ascii]* (1.0+(info->kern/40.0)))+uloverlap);
+ // 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;
+ 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,
ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize,
@@ -819,11 +1129,11 @@ struct chartrans *text_to_curve(Object *ob, int mode)
else {
outta = 0;
for (i= 0; (i<slen) && (outta==0); i++) {
- ascii = cu->str[i];
+ ascii = mem[i];
info = &(cu->strinfo[i]);
if (cu->sepchar == (i+1)) {
- cu->str[0] = ascii;
- cu->str[1] = 0;
+ mem[0] = ascii;
+ mem[1] = 0;
cu->strinfo[0]= *info;
cu->pos = 1;
cu->len = 1;
@@ -841,9 +1151,14 @@ struct chartrans *text_to_curve(Object *ob, int mode)
}
if(mode==FO_DUPLI) {
+ MEM_freeN(mem);
return chartransdata;
}
+errcse:
+ if(mem)
+ MEM_freeN(mem);
+
MEM_freeN(chartransdata);
return 0;
}
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
index 516bfb15f3f..1ebcd80b22b 100644
--- a/source/blender/blenlib/BLI_vfontdata.h
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -41,17 +41,36 @@
#include "DNA_listBase.h"
struct PackedFile;
+struct VFont;
#define MAX_VF_CHARS 256
typedef struct VFontData {
- ListBase nurbsbase[MAX_VF_CHARS];
- float resol[MAX_VF_CHARS];
- float width[MAX_VF_CHARS];
- float *points[MAX_VF_CHARS];
- char name[128];
+ ListBase characters;
+ // ListBase nurbsbase[MAX_VF_CHARS];
+ // float resol[MAX_VF_CHARS];
+ // float width[MAX_VF_CHARS];
+ // float *points[MAX_VF_CHARS];
+ char name[128];
} VFontData;
+typedef struct VChar {
+ struct VChar *next, *prev;
+ ListBase nurbsbase;
+ unsigned long index;
+ float resol;
+ float width;
+ float *points;
+} VChar;
+
+struct TmpFont
+{
+ struct TmpFont *next, *prev;
+ struct PackedFile *pf;
+ struct VFont *vfont;
+};
+
+
/**
* Construct a new VFontData structure from
* PostScript font data in a PackedFile.
@@ -75,5 +94,10 @@ BLI_vfontdata_from_psfont(
VFontData*
BLI_vfontdata_from_freetypefont(
struct PackedFile *pf);
+
+ int
+BLI_vfontchar_from_freetypefont(
+ struct VFont *vfont, unsigned long character);
+
#endif
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 5e1300e9cdf..f20be8ce828 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -54,8 +54,10 @@
#include "BIF_toolbox.h"
+#include "BKE_global.h"
#include "BKE_utildefines.h"
+#include "DNA_vfont_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_curve_types.h"
@@ -67,18 +69,265 @@ static FT_Library library;
static FT_Error err;
-static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
{
// Blender
- VFontData *vfd;
struct Nurb *nu;
+ struct VChar *che;
struct BezTriple *bezt;
+
+ // Freetype2
+ FT_GlyphSlot glyph;
+ FT_UInt glyph_index;
+ FT_Outline ftoutline;
+ const char *fontname;
+ float scale, height;
+ float dx, dy;
+ int i,j,k,l,m=0;
+
+ // Variables
+ int *npoints;
+ int *onpoints;
+
+ // adjust font size
+ height= ((double) face->bbox.yMax - (double) face->bbox.yMin);
+ if(height != 0.0)
+ scale = 1.0 / height;
+ else
+ scale = 1.0 / 1000.0;
+
+ //
+ // Generate the character 3D data
+ //
+ // Get the FT Glyph index and load the Glyph
+ glyph_index= FT_Get_Char_Index(face, charcode);
+ err= FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+
+ // If loading succeeded, convert the FT glyph to the internal format
+ if(!err)
+ {
+ // First we create entry for the new character to the character list
+ che= (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
+ BLI_addtail(&vfd->characters, che);
+
+ // Take some data for modifying purposes
+ glyph= face->glyph;
+ ftoutline= glyph->outline;
+
+ // Set the width and character code
+ che->index= charcode;
+ che->width= glyph->advance.x * scale;
+
+ // Start converting the FT data
+ npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
+ onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
+
+ // calculate total points of each contour
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ if(j == 0)
+ npoints[j] = ftoutline.contours[j] + 1;
+ else
+ npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
+ }
+
+ // get number of on-curve points for beziertriples (including conic virtual on-points)
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ l = 0;
+ for(k = 0; k < npoints[j]; k++) {
+ if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+ if(ftoutline.tags[l] == FT_Curve_Tag_On)
+ onpoints[j]++;
+
+ if(k < npoints[j] - 1 )
+ if( ftoutline.tags[l] == FT_Curve_Tag_Conic &&
+ ftoutline.tags[l+1] == FT_Curve_Tag_Conic)
+ onpoints[j]++;
+ }
+ }
+
+ //contour loop, bezier & conic styles merged
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ // add new curve
+ nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
+ bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
+ BLI_addtail(&che->nurbsbase, nu);
+
+ nu->type= CU_BEZIER+CU_2D;
+ nu->pntsu = onpoints[j];
+ nu->resolu= 8;
+ nu->flagu= 1;
+ nu->bezt = bezt;
+
+ //individual curve loop, start-end
+ for(k = 0; k < npoints[j]; k++) {
+ if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+ if(k == 0) m = l;
+
+ //virtual conic on-curve points
+ if(k < npoints[j] - 1 )
+ {
+ if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+ dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
+ dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
+
+ //left handle
+ bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x)* scale) / 3.0;
+ bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y)* scale) / 3.0;
+
+ //midpoint (virtual on-curve point)
+ bezt->vec[1][0] = dx;
+ bezt->vec[1][1] = dy;
+
+ //right handle
+ bezt->vec[2][0] = (dx + (2 * ftoutline.points[l+1].x)* scale) / 3.0;
+ bezt->vec[2][1] = (dy + (2 * ftoutline.points[l+1].y)* scale) / 3.0;
+ bezt->h1= bezt->h2= HD_ALIGN;
+ bezt++;
+ }
+ }
+
+ //on-curve points
+ if(ftoutline.tags[l] == FT_Curve_Tag_On) {
+ //left handle
+ if(k > 0) {
+ if(ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
+ bezt->vec[0][0] = ftoutline.points[l-1].x* scale;
+ bezt->vec[0][1] = ftoutline.points[l-1].y* scale;
+ bezt->h1= HD_FREE;
+ } else if(ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
+ bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x))* scale / 3.0;
+ bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y))* scale / 3.0;
+ bezt->h1= HD_FREE;
+ } else {
+ bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l-1].x)* scale / 3.0;
+ bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l-1].y)* scale / 3.0;
+ bezt->h1= HD_VECT;
+ }
+ } else { //first point on curve
+ if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
+ bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
+ bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
+ bezt->h1= HD_FREE;
+ } else if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
+ bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x))* scale / 3.0 ;
+ bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y))* scale / 3.0 ;
+ bezt->h1= HD_FREE;
+ } else {
+ bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x)* scale / 3.0;
+ bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y)* scale / 3.0;
+ bezt->h1= HD_VECT;
+ }
+ }
+
+ //midpoint (on-curve point)
+ bezt->vec[1][0] = ftoutline.points[l].x* scale;
+ bezt->vec[1][1] = ftoutline.points[l].y* scale;
+
+ //right handle
+ if(k < (npoints[j] - 1)) {
+ if(ftoutline.tags[l+1] == FT_Curve_Tag_Cubic) {
+ bezt->vec[2][0] = ftoutline.points[l+1].x* scale;
+ bezt->vec[2][1] = ftoutline.points[l+1].y* scale;
+ bezt->h2= HD_FREE;
+ } else if(ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+ bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l+1].x))* scale / 3.0;
+ bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l+1].y))* scale / 3.0;
+ bezt->h2= HD_FREE;
+ } else {
+ bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l+1].x)* scale / 3.0;
+ bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l+1].y)* scale / 3.0;
+ bezt->h2= HD_VECT;
+ }
+ } else { //last point on curve
+ if(ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
+ bezt->vec[2][0] = ftoutline.points[m].x* scale;
+ bezt->vec[2][1] = ftoutline.points[m].y* scale;
+ bezt->h2= HD_FREE;
+ } else if(ftoutline.tags[m] == FT_Curve_Tag_Conic) {
+ bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x))* scale / 3.0 ;
+ bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y))* scale / 3.0 ;
+ bezt->h2= HD_FREE;
+ } else {
+ bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[m].x)* scale / 3.0;
+ bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[m].y)* scale / 3.0;
+ bezt->h2= HD_VECT;
+ }
+ }
+
+ // get the handles that are aligned, tricky...
+ // DistVL2Dfl, check if the three beztriple points are on one line
+ // VecLenf, see if there's a distance between the three points
+ // VecLenf again, to check the angle between the handles
+ // finally, check if one of them is a vector handle
+ if((DistVL2Dfl(bezt->vec[0],bezt->vec[1],bezt->vec[2]) < 0.001) &&
+ (VecLenf(bezt->vec[0], bezt->vec[1]) > 0.0001) &&
+ (VecLenf(bezt->vec[1], bezt->vec[2]) > 0.0001) &&
+ (VecLenf(bezt->vec[0], bezt->vec[2]) > 0.0002) &&
+ (VecLenf(bezt->vec[0], bezt->vec[2]) > MAX2(VecLenf(bezt->vec[0], bezt->vec[1]), VecLenf(bezt->vec[1], bezt->vec[2]))) &&
+ bezt->h1 != HD_VECT && bezt->h2 != HD_VECT)
+ {
+ bezt->h1= bezt->h2= HD_ALIGN;
+ }
+ bezt++;
+ }
+ }
+ }
+ }
+
+ if(npoints) MEM_freeN(npoints);
+ if(onpoints) MEM_freeN(onpoints);
+}
+
+int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
+{
// Freetype2
- FT_Face face;
- FT_GlyphSlot glyph;
- FT_UInt glyph_index;
- FT_Outline ftoutline;
+ FT_Face face;
+ FT_UInt glyph_index;
+ struct TmpFont *tf;
+
+ // Find the correct FreeType font
+ tf= G.ttfdata.first;
+ while(tf)
+ {
+ if(tf->vfont == vfont)
+ break;
+ tf= tf->next;
+ }
+
+ // What, no font found. Something strange here
+ if(!tf) return FALSE;
+
+ // Load the font to memory
+ if(tf->pf)
+ {
+ err= FT_New_Memory_Face( library,
+ tf->pf->data,
+ tf->pf->size,
+ 0,
+ &face);
+ }
+ else
+ err= TRUE;
+
+ // Read the char
+ freetypechar_to_vchar(face, charcode, vfont->data);
+
+ // And everything went ok
+ return TRUE;
+}
+
+
+static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+{
+ // Variables
+ FT_Face face;
+ FT_ULong charcode = 0, lcode;
+ FT_UInt glyph_index;
+ FT_UInt temp;
+ const char *fontname;
+ VFontData *vfd;
+
/*
FT_CharMap found = 0;
FT_CharMap charmap;
@@ -86,10 +335,6 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
int n;
*/
- const char *fontname;
- float scale, height;
- float dx, dy;
- int i, j, k, l, m =0;
// load the freetype font
err = FT_New_Memory_Face( library,
@@ -125,187 +370,52 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
fontname = FT_Get_Postscript_Name(face);
strcpy(vfd->name, (fontname == NULL) ? "Fontname not available" : fontname);
- // adjust font size
- height = ((double) face->bbox.yMax - (double) face->bbox.yMin);
-
- if(height != 0.0)
- scale = 1.0 / height;
- else
- scale = 1.0 / 1000.0;
+ // Extract the first 256 character from TTF
+ lcode= charcode= FT_Get_First_Char(face, &glyph_index);
- // extract generic ascii character range
- for(i = myMIN_ASCII; i <= myMAX_ASCII; i++) {
- int *npoints = NULL; //total points of each contour
- int *onpoints = NULL; //num points on curve
+ // No charmap found from the ttf so we need to figure it out
+ if(glyph_index == 0)
+ {
+ FT_CharMap found = 0;
+ FT_CharMap charmap;
+ int n;
- glyph_index = FT_Get_Char_Index( face, i );
- err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
-
- if(!err) {
- glyph = face->glyph;
- ftoutline = glyph->outline;
-
- vfd->width[i] = glyph->advance.x* scale;
-
- npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
- onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
-
- // calculate total points of each contour
- for(j = 0; j < ftoutline.n_contours; j++) {
- if(j == 0)
- npoints[j] = ftoutline.contours[j] + 1;
- else
- npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
- }
-
- // get number of on-curve points for beziertriples (including conic virtual on-points)
- for(j = 0; j < ftoutline.n_contours; j++) {
- l = 0;
- for(k = 0; k < npoints[j]; k++) {
- if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
-
- if(ftoutline.tags[l] == FT_Curve_Tag_On)
- onpoints[j]++;
-
- if(k < npoints[j] - 1 )
- if( ftoutline.tags[l] == FT_Curve_Tag_Conic &&
- ftoutline.tags[l+1] == FT_Curve_Tag_Conic)
- onpoints[j]++;
- }
+ for ( n = 0; n < face->num_charmaps; n++ )
+ {
+ charmap = face->charmaps[n];
+ if (charmap->encoding == FT_ENCODING_APPLE_ROMAN)
+ {
+ found = charmap;
+ break;
}
+ }
- //contour loop, bezier & conic styles merged
- for(j = 0; j < ftoutline.n_contours; j++) {
- // add new curve
- nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
- bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
- BLI_addtail(&vfd->nurbsbase[i], nu);
-
- nu->type= CU_BEZIER+CU_2D;
- nu->pntsu = onpoints[j];
- nu->resolu= 8;
- nu->flagu= 1;
- nu->bezt = bezt;
-
- //individual curve loop, start-end
- for(k = 0; k < npoints[j]; k++) {
- if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
- if(k == 0) m = l;
-
- //virtual conic on-curve points
- if(k < npoints[j] - 1 )
- if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
- dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
- dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
-
- //left handle
- bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x)* scale) / 3.0;
- bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y)* scale) / 3.0;
-
- //midpoint (virtual on-curve point)
- bezt->vec[1][0] = dx;
- bezt->vec[1][1] = dy;
-
- //right handle
- bezt->vec[2][0] = (dx + (2 * ftoutline.points[l+1].x)* scale) / 3.0;
- bezt->vec[2][1] = (dy + (2 * ftoutline.points[l+1].y)* scale) / 3.0;
-
- bezt->h1= bezt->h2= HD_ALIGN;
- bezt++;
- }
+ err = FT_Set_Charmap( face, found );
- //on-curve points
- if(ftoutline.tags[l] == FT_Curve_Tag_On) {
- //left handle
- if(k > 0) {
- if(ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
- bezt->vec[0][0] = ftoutline.points[l-1].x* scale;
- bezt->vec[0][1] = ftoutline.points[l-1].y* scale;
- bezt->h1= HD_FREE;
- } else if(ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
- bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x))* scale / 3.0;
- bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y))* scale / 3.0;
- bezt->h1= HD_FREE;
- } else {
- bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l-1].x)* scale / 3.0;
- bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l-1].y)* scale / 3.0;
- bezt->h1= HD_VECT;
- }
- } else { //first point on curve
- if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
- bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
- bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
- bezt->h1= HD_FREE;
- } else if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
- bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x))* scale / 3.0 ;
- bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y))* scale / 3.0 ;
- bezt->h1= HD_FREE;
- } else {
- bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x)* scale / 3.0;
- bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y)* scale / 3.0;
- bezt->h1= HD_VECT;
- }
- }
+ if( err )
+ return NULL;
- //midpoint (on-curve point)
- bezt->vec[1][0] = ftoutline.points[l].x* scale;
- bezt->vec[1][1] = ftoutline.points[l].y* scale;
+ lcode= charcode= FT_Get_First_Char(face, &glyph_index);
+ }
- //right handle
- if(k < (npoints[j] - 1)) {
- if(ftoutline.tags[l+1] == FT_Curve_Tag_Cubic) {
- bezt->vec[2][0] = ftoutline.points[l+1].x* scale;
- bezt->vec[2][1] = ftoutline.points[l+1].y* scale;
- bezt->h2= HD_FREE;
- } else if(ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
- bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l+1].x))* scale / 3.0;
- bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l+1].y))* scale / 3.0;
- bezt->h2= HD_FREE;
- } else {
- bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l+1].x)* scale / 3.0;
- bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l+1].y)* scale / 3.0;
- bezt->h2= HD_VECT;
- }
- } else { //last point on curve
- if(ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
- bezt->vec[2][0] = ftoutline.points[m].x* scale;
- bezt->vec[2][1] = ftoutline.points[m].y* scale;
- bezt->h2= HD_FREE;
- } else if(ftoutline.tags[m] == FT_Curve_Tag_Conic) {
- bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x))* scale / 3.0 ;
- bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y))* scale / 3.0 ;
- bezt->h2= HD_FREE;
- } else {
- bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[m].x)* scale / 3.0;
- bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[m].y)* scale / 3.0;
- bezt->h2= HD_VECT;
- }
- }
+ // Load characters
+ while(charcode < 256)
+ {
+ // Generate the font data
+ freetypechar_to_vchar(face, charcode, vfd);
- // get the handles that are aligned, tricky...
- // DistVL2Dfl, check if the three beztriple points are on one line
- // VecLenf, see if there's a distance between the three points
- // VecLenf again, to check the angle between the handles
- // finally, check if one of them is a vector handle
- if((DistVL2Dfl(bezt->vec[0],bezt->vec[1],bezt->vec[2]) < 0.001) &&
- (VecLenf(bezt->vec[0], bezt->vec[1]) > 0.0001) &&
- (VecLenf(bezt->vec[1], bezt->vec[2]) > 0.0001) &&
- (VecLenf(bezt->vec[0], bezt->vec[2]) > 0.0002) &&
- (VecLenf(bezt->vec[0], bezt->vec[2]) > MAX2(VecLenf(bezt->vec[0], bezt->vec[1]), VecLenf(bezt->vec[1], bezt->vec[2]))) &&
- bezt->h1 != HD_VECT && bezt->h2 != HD_VECT)
- {
- bezt->h1= bezt->h2= HD_ALIGN;
- }
- bezt++;
- }
- }
- }
- }
+ // Next glyph
+ charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
- if(npoints) MEM_freeN(npoints);
- if(onpoints) MEM_freeN(onpoints);
+ // Check that we won't start infinite loop
+ if(charcode <= lcode)
+ break;
+ lcode = charcode;
}
- return vfd;
+
+ err = FT_Set_Charmap( face, FT_ENCODING_UNICODE );
+
+ return vfd;
}
@@ -393,6 +503,30 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
return vfd;
}
+int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
+{
+ int success = FALSE;
+
+ if(!vfont) return FALSE;
+
+ // Init Freetype
+ err = FT_Init_FreeType(&library);
+ if(err) {
+ error("Failed to load the Freetype font library");
+ return 0;
+ }
+
+ // Load the character
+ success = objchr_to_ftvfontdata(vfont, character);
+ if(success == FALSE) return FALSE;
+
+ // Free Freetype
+ FT_Done_FreeType(library);
+
+ // Ahh everything ok
+ return TRUE;
+}
+
#endif // WITH_FREETYPE2
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
index f7fbf7e3d16..2fccf09805b 100644
--- a/source/blender/blenlib/intern/psfont.c
+++ b/source/blender/blenlib/intern/psfont.c
@@ -1956,6 +1956,7 @@ static VFontData *objfnt_to_vfontdata(objfnt *fnt)
struct Nurb *nu;
struct BezTriple *bezt, *bez2;
float scale, dx, dy;
+ struct VChar *che;
if (!fnt || (fnt->type!=SP_TYPE)) {
return NULL;
@@ -1967,7 +1968,10 @@ static VFontData *objfnt_to_vfontdata(objfnt *fnt)
for (i = 0; i < MAX_VF_CHARS; i++) {
cd = getchardesc(fnt, i);
if (cd && cd->data && cd->datalen) {
- vfd->width[i] = scale * cd->movex;
+ che = (VChar *) MEM_callocN(sizeof(VChar), "objfnt_char");
+ BLI_addtail(&vfd->characters, che);
+ che->index = i;
+ che->width = scale * cd->movex;
_data = data = cd->data;
@@ -2015,7 +2019,7 @@ static VFontData *objfnt_to_vfontdata(objfnt *fnt)
nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
if (nu != 0 && bezt != 0) {
- BLI_addtail(&vfd->nurbsbase[i], nu);
+ BLI_addtail(&che->nurbsbase, nu);
nu->type= CU_BEZIER+CU_2D;
nu->pntsu = count;
nu->resolu= 8;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 57c5c90555e..c54363e692a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -848,6 +848,13 @@ static void write_mballs(WriteData *wd, ListBase *idbase)
}
}
+int amount_of_chars(char *str)
+{
+ // Since the data is saved as UTF-8 to the cu->str
+ // The cu->len is not same as the strlen(cu->str)
+ return strlen(str);
+}
+
static void write_curves(WriteData *wd, ListBase *idbase)
{
Curve *cu;
@@ -863,7 +870,7 @@ static void write_curves(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
if(cu->vfont) {
- writedata(wd, DATA, cu->len+1, cu->str);
+ writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str);
writestruct(wd, DATA, "CharInfo", cu->len, cu->strinfo);
writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);
}
diff --git a/source/blender/include/BIF_editfont.h b/source/blender/include/BIF_editfont.h
index 372630da8e2..081bea67145 100644
--- a/source/blender/include/BIF_editfont.h
+++ b/source/blender/include/BIF_editfont.h
@@ -30,16 +30,26 @@
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
+#include <wchar.h>
+
#ifndef BIF_EDITFONT_H
#define BIF_EDITFONT_H
struct Text;
extern char *BIF_lorem;
-extern char *copybuf;
-extern char *copybufinfo;
+extern wchar_t *copybuf;
+extern wchar_t *copybufinfo;
+
+typedef struct unicodect
+{
+ char *name;
+ char *longname;
+ int start;
+ int end;
+} unicodect;
-void do_textedit(unsigned short event, short val, char _ascii);
+void do_textedit(unsigned short event, short val, unsigned long _ascii);
void make_editText(void);
void load_editText(void);
void remake_editText(void);
diff --git a/source/blender/include/BIF_interface.h b/source/blender/include/BIF_interface.h
index 875bdbf3564..753bda9a9d3 100644
--- a/source/blender/include/BIF_interface.h
+++ b/source/blender/include/BIF_interface.h
@@ -151,6 +151,7 @@ struct ScrArea;
#define HSVCUBE (26<<9)
#define PULLDOWN (27<<9)
#define ROUNDBOX (28<<9)
+#define CHARTAB (29<<9)
#define BUTTYPE (31<<9)
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index eff682e4116..011c13eb0db 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -408,6 +408,12 @@ enum {
#define B_STYLETOSELU 2213
#define B_STYLETOSELI 2214
+#define B_SETCHAR 2215
+#define B_SETUPCHAR 2216
+#define B_SETDOWNCHAR 2217
+#define B_SETCAT 2218
+#define B_SETUNITEXT 2219
+
/* *********************** */
#define B_ARMBUTS 2400
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 6e21aa2ccdb..c44d5d9b023 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -86,6 +86,7 @@
#include "BLI_arithb.h"
#include "BLI_vfontdata.h"
#include "BLI_editVert.h"
+#include "BLI_dynstr.h"
#include "BSE_filesel.h"
@@ -159,6 +160,202 @@ short uv_calc_mapdir= 1, uv_calc_mapalign= 1, facesel_draw_edges= 0;
extern ListBase editNurb;
+/* *************************** Unicode Character Groups ****************** */
+unicodect uctabname[125] = {
+ {"All", "All", 0x0000, 0xffff},
+ {"Basic Latin", "Basic Latin", 0x0000, 0x007f},
+ {"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff},
+
+ {"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
+ {"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F},
+ {"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
+
+ {"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
+ {"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
+
+ {"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
+ {"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
+ {"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
+
+ {"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
+ {"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
+
+ {"Armenian", "Armenian", 0x0530, 0x058f},
+ {"Hebrew", "Hebrew", 0x0590, 0x05ff},
+
+
+ {"Arabic", "Arabic", 0x0600, 0x06ff},
+ {"Syriac", "Syriac", 0x0700, 0x074f},
+
+ {"Thaana", "Thaana", 0x0780, 0x07bf},
+ {"Devanagari", "Devanagari", 0x0900, 0x097f},
+
+ {"Bengali", "Bengali", 0x0980, 0x09ff},
+ {"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
+
+ {"Gujarati", "Gujarati", 0x0a80, 0x0aff},
+ {"Oriya", "Oriya", 0x0b00, 0x0b7f},
+
+ {"Tamil", "Tamil", 0x0b80, 0x0bff},
+ {"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
+
+ {"Kannada", "Kannada", 0x0c80, 0x0cff},
+ {"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
+
+ {"Sinhala", "Sinhala", 0x0d80, 0x0dff},
+ {"Thai", "Thai", 0x0e00, 0x0e7f},
+
+ {"Lao", "Lao", 0x0e80, 0x0eff},
+ {"Tibetan", "Tibetan", 0x0f00, 0x0fff},
+
+ {"Myanmar", "Myanmar", 0x1000, 0x109f},
+ {"Georgian", "Georgian", 0x10a0, 0x10ff},
+
+ {"Ethiopic", "Ethiopic", 0x1200, 0x137f},
+
+ {"Cherokee", "Cherokee", 0x13a0, 0x13ff},
+ {"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
+
+ {"Ogham", "Ogham", 0x1680, 0x169f},
+ {"Runic", "Runic", 0x16a0, 0x16ff},
+
+ {"Tagalog", "Tagalog", 0x1700, 0x171f},
+ {"Hanunoo", "Hanunoo", 0x1720, 0x173f},
+
+ {"Buhid", "Buhid", 0x1740, 0x175f},
+ {"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
+
+ {"Khmer", "Khmer", 0x1780, 0x17ff},
+ {"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
+
+ {"Mongolian", "Mongolian", 0x1800, 0x18af},
+
+ {"Limbu", "Limbu", 0x1900, 0x194f},
+ {"Tai Le", "Tai Le", 0x1950, 0x197f},
+
+ {"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
+
+
+ {"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
+ {"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
+
+ {"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
+ {"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
+
+ {"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
+ {"Numb. Forms", "Number Forms", 0x2150, 0x218f},
+
+ {"Arrows", "Arrows", 0x2190, 0x21ff},
+ {"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
+
+ {"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
+ {"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
+
+ {"OCR", "Optical Character Recognition", 0x2440, 0x245f},
+ {"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
+
+ {"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
+ {"BLock Elem.", "Block Elements", 0x2580, 0x259f},
+
+ {"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
+ {"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
+
+ {"Dingbats", "Dingbats", 0x2700, 0x27bf},
+ {"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
+
+ {"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
+ {"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
+
+ {"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
+ {"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
+
+ {"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
+ {"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
+
+ {"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
+
+ {"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
+
+ {"Hiragana", "Hiragana", 0x3040, 0x309f},
+ {"Katakana", "Katakana", 0x30a0, 0x30ff},
+ {"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
+
+ {"Bopomofo", "Bopomofo", 0x3100, 0x312f},
+ {"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
+
+ {"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
+ {"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
+ {"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
+
+ {"Kanbun", "Kanbun", 0x3190, 0x319f},
+
+
+
+ {"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
+
+ {"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
+ {"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
+
+ {"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
+
+ {"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
+ {"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
+
+ {"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
+ {"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
+ {"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
+ {"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
+ {"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
+ {"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
+ {"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
+ {"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
+ {"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
+ {"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
+
+ {"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
+
+ {"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
+ {"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
+
+ {"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
+
+ {"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
+
+ {"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
+
+ {"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
+ {"Specials", "Specials", 0xfff0, 0xffff},
+
+ {"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
+ {"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
+
+ {"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
+ {"Old Italic", "Old Italic", 0x10300, 0x1032f},
+
+ {"Gothic", "Gothic", 0x10330, 0x1034f},
+ {"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
+
+ {"Deseret", "Deseret", 0x10400, 0x1044f},
+ {"Shavian", "Shavian", 0x10450, 0x1047f},
+
+ {"Osmanya", "Osmanya", 0x10480, 0x104af},
+ {"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
+
+ {"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
+ {"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
+
+ {"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
+ {"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
+
+
+ {"Tags", "Tags", 0xe0000, 0xe007f},
+ {"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
+
+ {"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
+ {"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
+
+};
+
/* *************************** static functions prototypes ****************** */
VFont *exist_vfont(char *str);
@@ -1268,6 +1465,11 @@ static void load_buts_vfont(char *name)
allqueue(REDRAWBUTSEDIT, 0);
}
+static void set_unicode_text_fs(char *file)
+{
+ if (file > 0) paste_unicodeText(file);
+}
+
void do_fontbuts(unsigned short event)
{
Curve *cu;
@@ -1275,6 +1477,9 @@ void do_fontbuts(unsigned short event)
Object *ob;
ScrArea *sa;
char str[80];
+ int ctevt;
+ char *ctmenu;
+ DynStr *ds;
int i, style=0;
ob= OBACT;
@@ -1422,6 +1627,74 @@ void do_fontbuts(unsigned short event)
}
}
break;
+
+ case B_SETCHAR:
+ G.charmin = 0x0000;
+ G.charmax = 0xffff;
+ if(G.charstart < 0)
+ G.charstart = 0;
+ if(G.charstart > (0xffff - 12*6))
+ G.charstart = 0xffff - (12*6);
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_SETUPCHAR:
+ G.charstart = G.charstart - (12*6);
+ if(G.charstart < 0)
+ G.charstart = 0;
+ if(G.charstart < G.charmin)
+ G.charstart = G.charmin;
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_SETCAT:
+ // Create new dynamic string
+ ds = BLI_dynstr_new();
+
+ // Fill the dynamic string with entries
+ for(i=0;i<104;i++)
+ {
+ BLI_dynstr_append(ds, "|");
+ BLI_dynstr_append(ds, uctabname[i].name);
+ }
+
+ // Create the menu string from dyn string
+ ctmenu = BLI_dynstr_get_cstring(ds);
+
+ // Call the popup menu
+ ctevt = pupmenu_col(ctmenu, 40);
+ G.charstart = uctabname[ctevt-1].start;
+ G.charmin = uctabname[ctevt-1].start;
+ G.charmax = uctabname[ctevt-1].end;
+
+ // Free all data
+ BLI_dynstr_free(ds);
+ MEM_freeN(ctmenu);
+
+ // And refresh
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSEDIT, 0);
+
+ break;
+
+ case B_SETDOWNCHAR:
+ G.charstart = G.charstart + (12*6);
+ if(G.charstart > (0xffff - 12*6))
+ G.charstart = 0xffff - (12*6);
+ if(G.charstart > G.charmax - 12*6)
+ G.charstart = G.charmax - 12*6;
+ allqueue(REDRAWBUTSEDIT, 0);
+ break;
+
+ case B_SETUNITEXT:
+ sa= closest_bigger_area();
+ areawinset(sa->win);
+
+ if(ob==G.obedit) {
+ activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
+ }
+ break;
+
case B_TEXTONCURVE:
if(ob) {
cu= ob->data;
@@ -1437,6 +1710,32 @@ void do_fontbuts(unsigned short event)
}
}
+static void editing_panel_char_type(Object *ob, Curve *cu)
+{
+ uiBlock *block;
+
+ block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
+ uiNewPanelTabbed("Font", "Editing");
+ if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0)
+ return;
+
+ // Set the selected font
+ G.selfont = cu->vfont;
+
+ uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT, 0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
+
+ // Unicode categorization selection button
+ uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
+ uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
+
+ // Character selection button
+ uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
+
+ // Buttons to change the max, min
+ uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
+ uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
+}
+
static void editing_panel_font_type(Object *ob, Curve *cu)
{
uiBlock *block;
@@ -3354,6 +3653,13 @@ void editing_panels()
editing_panel_links(ob); // no editmode!
editing_panel_curve_type(ob, cu);
editing_panel_font_type(ob, cu);
+
+#ifdef INTERNATIONAL
+ if(G.obedit)
+ {
+ editing_panel_char_type(ob, cu);
+ }
+#endif
editing_panel_modifiers(ob);
break;
diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c
index 278c70eb15f..4e2857a76bb 100644
--- a/source/blender/src/editfont.c
+++ b/source/blender/src/editfont.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
+#include <wchar.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -86,7 +87,7 @@ int textediting=0;
extern struct SelBox *selboxes; /* from blenkernel/font.c */
-static char findaccent(char char1, char code)
+static char findaccent(char char1, unsigned int code)
{
char new= 0;
@@ -217,15 +218,25 @@ static char findaccent(char char1, char code)
else return char1;
}
-char *copybuf=NULL;
-char *copybufinfo=NULL;
+wchar_t *copybuf=NULL;
+wchar_t *copybufinfo=NULL;
-static char *textbuf=NULL;
+static wchar_t *textbuf=NULL;
static CharInfo *textbufinfo=NULL;
-static char *oldstr=NULL;
+static wchar_t *oldstr=NULL;
static CharInfo *oldstrinfo=NULL;
-static int insert_into_textbuf(Curve *cu, char c)
+void update_string(Curve *cu)
+{
+ int len;
+
+ MEM_freeN(cu->str);
+ len = wcsleninu8(textbuf);
+ cu->str = MEM_callocN(len + sizeof(wchar_t), "str");
+ wcs2utf8s(cu->str, textbuf);
+}
+
+static int insert_into_textbuf(Curve *cu, unsigned long c)
{
if (cu->len<MAXTEXT-1) {
int x;
@@ -244,6 +255,8 @@ static int insert_into_textbuf(Curve *cu, char c)
cu->len++;
textbuf[cu->len]='\0';
+ update_string(cu);
+
return 1;
} else {
return 0;
@@ -280,16 +293,36 @@ void add_lorem(void)
void load_3dtext_fs(char *file)
{
FILE *fp;
- int c;
+ int filelen;
+ char *strp;
+ Curve *cu=G.obedit->data;
fp= fopen(file, "r");
if (!fp) return;
+
+ fseek(fp, 0L, SEEK_END);
+ filelen = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ strp = MEM_callocN(filelen+4, "tempstr");
+
+ filelen = fread(strp, 1, filelen, fp);
+ fclose(fp);
+ strp[filelen]= 0;
- while (!feof(fp)) {
- c = fgetc(fp);
- if (c!=EOF) insert_into_textbuf(OBACT->data, c);
+ if(cu->len+filelen<MAXTEXT)
+ {
+ int tmplen;
+ wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+ tmplen = utf8towchar_(mem, strp);
+ wcscat(textbuf, mem);
+ MEM_freeN(mem);
+ cu->len += tmplen;
+ cu->pos= cu->len;
}
- fclose(fp);
+ MEM_freeN(strp);
+
+ update_string(cu);
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
@@ -479,6 +512,7 @@ static int killselection(int ins) /* 1 == new character */
direction = getselection(&selstart, &selend);
if (direction) {
+ int size;
if (ins) offset = 1;
if (cu->pos >= selstart) cu->pos = selstart+offset;
if ((direction == -1) && ins) {
@@ -487,7 +521,8 @@ static int killselection(int ins) /* 1 == new character */
}
getfrom = selend+offset;
if (ins==0) getfrom++;
- memmove(textbuf+selstart, textbuf+getfrom, (cu->len-selstart)+offset);
+ size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset*sizeof(wchar_t));
+ memmove(textbuf+selstart, textbuf+getfrom, size);
memmove(textbufinfo+selstart, textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
cu->len -= (selend-selstart)+offset;
cu->selstart = cu->selend = 0;
@@ -500,7 +535,7 @@ static void copyselection(void)
int selstart, selend;
if (getselection(&selstart, &selend)) {
- memcpy(copybuf, textbuf+selstart, (selend-selstart)+1);
+ memcpy(copybuf, textbuf+selstart, ((selend-selstart)+1)*sizeof(wchar_t));
copybuf[(selend-selstart)+1]=0;
memcpy(copybufinfo, textbufinfo+selstart, ((selend-selstart)+1)*sizeof(CharInfo));
}
@@ -509,11 +544,12 @@ static void copyselection(void)
static void pasteselection(void)
{
Curve *cu= G.obedit->data;
- int len= strlen(copybuf);
+ int len= wcslen(copybuf);
if (len) {
- memmove(textbuf+cu->pos+len, textbuf+cu->pos, cu->len-cu->pos+1);
- memcpy(textbuf+cu->pos, copybuf, len);
+ int size = (cu->len * sizeof(wchar_t)) - (cu->pos*sizeof(wchar_t)) + sizeof(wchar_t);
+ memmove(textbuf+cu->pos+len, textbuf+cu->pos, size);
+ memcpy(textbuf+cu->pos, copybuf, len * sizeof(wchar_t));
memmove(textbufinfo+cu->pos+len, textbufinfo+cu->pos, (cu->len-cu->pos+1)*sizeof(CharInfo));
memcpy(textbufinfo+cu->pos, copybufinfo, len*sizeof(CharInfo));
@@ -564,12 +600,12 @@ int mat_to_sel(void) {
return 0;
}
-void do_textedit(unsigned short event, short val, char _ascii)
+void do_textedit(unsigned short event, short val, unsigned long _ascii)
{
Curve *cu;
static int accentcode= 0;
int x, doit=0, cursmove=0;
- int ascii = _ascii;
+ unsigned long ascii = _ascii;
short kern;
cu= G.obedit->data;
@@ -608,7 +644,6 @@ void do_textedit(unsigned short event, short val, char _ascii)
else if(ascii=='>') ascii= 187;
else if(ascii=='<') ascii= 171;
}
-
if(ascii==1001) {
int file, filelen;
char *strp;
@@ -627,9 +662,14 @@ void do_textedit(unsigned short event, short val, char _ascii)
read(file, strp, filelen);
close(file);
strp[filelen]= 0;
+
if(cu->len+filelen<MAXTEXT) {
- strcat( textbuf, strp);
- cu->len= strlen(textbuf);
+ int tmplen;
+ wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+ tmplen = utf8towchar_(mem, strp);
+ wcscat(textbuf, mem);
+ MEM_freeN(mem);
+ cu->len += tmplen;
cu->pos= cu->len;
}
MEM_freeN(strp);
@@ -644,6 +684,11 @@ void do_textedit(unsigned short event, short val, char _ascii)
doit= 1;
}
+ else
+ {
+ insert_into_textbuf(cu, ascii);
+ doit = 1;
+ }
}
else if(val) {
cursmove= 0;
@@ -841,6 +886,7 @@ void do_textedit(unsigned short event, short val, char _ascii)
if ((G.qual & LR_SHIFTKEY)==0) {
if (cu->selstart) {
cu->selstart = cu->selend = 0;
+ update_string(cu);
text_to_curve(G.obedit, FO_SELCHANGE);
allqueue(REDRAWVIEW3D, 0);
}
@@ -860,6 +906,7 @@ void do_textedit(unsigned short event, short val, char _ascii)
G.obedit->actcol = textbufinfo[cu->pos-1].mat_nr;
}
allqueue(REDRAWBUTSEDIT, 0);
+ update_string(cu);
text_to_curve(G.obedit, cursmove);
if (cursmove && (G.qual & LR_SHIFTKEY)) {
cu->selend = cu->pos;
@@ -874,16 +921,64 @@ void do_textedit(unsigned short event, short val, char _ascii)
}
}
+void paste_unicodeText(char *filename)
+{
+ Curve *cu;
+ int filelen, doit= 0;
+ char *strp;
+ FILE *fp = NULL;
+
+ fp= fopen(filename, "r");
+
+ if(fp) {
+ cu= G.obedit->data;
+
+ fseek( fp, 0L, SEEK_END );
+ filelen = ftell( fp );
+ fseek( fp, 0L, SEEK_SET );
+
+ strp= MEM_mallocN(filelen+4, "tempstr");
+ //fread() instead of read(),
+ //because windows read() converts text to DOS \r\n linebreaks
+ //causing double linebreaks in the 3d text
+ filelen = fread(strp, 1, filelen, fp);
+ fclose(fp);
+ strp[filelen]= 0;
+
+
+ if(cu->len+filelen<MAXTEXT)
+ {
+ int tmplen;
+ wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
+ tmplen = utf8towchar_(mem, strp);
+// mem =utf8s2wc(strp);
+ wcscat(textbuf, mem);
+ MEM_freeN(mem);
+// cu->len = wcslen(textbuf);
+ cu->len += tmplen;
+ cu->pos= cu->len;
+ }
+ MEM_freeN(strp);
+ doit = 1;
+ }
+ if(doit) {
+ update_string(cu);
+ text_to_curve(G.obedit, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Paste text");
+ }
+}
void paste_editText(void)
{
Curve *cu;
- int file, filelen, doit= 0;
+ int filelen, doit= 0;
char *strp;
-
+ FILE *fp = NULL;
#ifdef WIN32
- file= open("C:\\windows\\temp\\cutbuf.txt", O_BINARY|O_RDONLY);
+ fp= fopen("C:\\windows\\temp\\cutbuf.txt", "r");
// The following is more likely to work on all Win32 installations.
// suggested by Douglas Toltzman. Needs windows include files...
@@ -900,26 +995,39 @@ void paste_editText(void)
}
*/
#else
- file= open("/tmp/.cutbuffer", O_BINARY|O_RDONLY);
+ fp= fopen("/tmp/.cutbuffer", "r");
#endif
- if(file>0) {
+ if(fp) {
cu= G.obedit->data;
- filelen = BLI_filesize(file);
+
+ fseek(fp, 0L, SEEK_END);
+ filelen = ftell( fp );
+ fseek(fp, 0L, SEEK_SET);
strp= MEM_mallocN(filelen+4, "tempstr");
- read(file, strp, filelen);
- close(file);
+ // fread() instead of read(),
+ // because windows read() converts text to DOS \r\n linebreaks
+ // causing double linebreaks in the 3d text
+ filelen = fread(strp, 1, filelen, fp);
+ fclose(fp);
strp[filelen]= 0;
+
if(cu->len+filelen<MAXTEXT) {
- strcat( textbuf, strp);
- cu->len= strlen(textbuf);
- cu->pos= cu->len;
+ int tmplen;
+ wchar_t *mem = MEM_callocN((sizeof(wchar_t) * filelen) + (4 * sizeof(wchar_t)), "temporary");
+ tmplen = utf8towchar_(mem, strp);
+ wcscat(textbuf, mem);
+ MEM_freeN(mem);
+ cu->len += tmplen;
+ cu->pos= cu->len;
}
MEM_freeN(strp);
doit = 1;
}
if(doit) {
+ update_string(cu);
+ text_to_curve(G.obedit, 0);
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
BIF_undo_push("Paste text");
@@ -930,19 +1038,23 @@ void paste_editText(void)
void make_editText(void)
{
Curve *cu;
-
cu= G.obedit->data;
- if(textbuf==NULL) textbuf= MEM_mallocN(MAXTEXT+4, "texteditbuf");
+
+ if(textbuf==NULL) textbuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditbuf");
if(textbufinfo==NULL) textbufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditbufinfo");
- if(copybuf==NULL) copybuf= MEM_callocN(MAXTEXT+4, "texteditcopybuf");
+ if(copybuf==NULL) copybuf= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "texteditcopybuf");
if(copybufinfo==NULL) copybufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditcopybufinfo");
- BLI_strncpy(textbuf, cu->str, MAXTEXT);
- cu->len= strlen(textbuf);
+ if(oldstr==NULL) oldstr= MEM_callocN((MAXTEXT+4)*sizeof(wchar_t), "oldstrbuf");
+
+ // Convert the original text to wchar_t
+ utf8towchar_(textbuf, cu->str);
+ wcscpy(oldstr, textbuf);
+
+ cu->len= wcslen(textbuf);
memcpy(textbufinfo, cu->strinfo, (cu->len)*sizeof(CharInfo));
- oldstr= cu->str;
+
oldstrinfo= cu->strinfo;
- cu->str= textbuf;
cu->strinfo= textbufinfo;
if(cu->pos>cu->len) cu->pos= cu->len;
@@ -951,6 +1063,9 @@ void make_editText(void)
cu->curinfo = textbufinfo[cu->pos-1];
} else cu->curinfo = textbufinfo[0];
+ // Convert to UTF-8
+ update_string(cu);
+
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
textediting= 1;
@@ -969,8 +1084,8 @@ void load_editText(void)
MEM_freeN(oldstrinfo);
oldstrinfo= NULL;
- cu->str= MEM_mallocN(cu->len+4, "textedit");
- strcpy(cu->str, textbuf);
+ update_string(cu);
+
cu->strinfo= MEM_callocN((cu->len+4)*sizeof(CharInfo), "texteditinfo");
memcpy(cu->strinfo, textbufinfo, (cu->len)*sizeof(CharInfo));
@@ -1000,7 +1115,10 @@ void remake_editText(void)
if(okee("Reload original text")==0) return;
- BLI_strncpy(textbuf, oldstr, MAXTEXT);
+ // Copy the oldstr to textbuf temporary global variable
+ wcscpy(textbuf, oldstr);
+
+ // Set the object length and position
cu= G.obedit->data;
cu->len= strlen(textbuf);
if(cu->pos>cu->len) cu->pos= cu->len;
@@ -1055,7 +1173,7 @@ void to_upper(void)
{
Curve *cu;
int len, ok;
- char *str;
+ wchar_t *str;
if(G.obedit==0) {
return;
@@ -1064,8 +1182,8 @@ void to_upper(void)
ok= 0;
cu= G.obedit->data;
- len= strlen(cu->str);
- str= cu->str;
+ len= wcslen(textbuf);
+ str= textbuf;
while(len) {
if( *str>=97 && *str<=122) {
ok= 1;
@@ -1076,8 +1194,8 @@ void to_upper(void)
}
if(ok==0) {
- len= strlen(cu->str);
- str= cu->str;
+ len= wcslen(textbuf);
+ str= textbuf;
while(len) {
if( *str>=65 && *str<=90) {
*str+= 32;
@@ -1089,6 +1207,8 @@ void to_upper(void)
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
BIF_undo_push("To upper");
+
+ update_string(cu);
}
@@ -1099,9 +1219,10 @@ static void undoFont_to_editFont(void *strv)
Curve *cu= G.obedit->data;
char *str= strv;
- strncpy(textbuf, str+2, MAXTEXT);
+ utf8towchar_(textbuf, str);
+
cu->pos= *((short *)str);
- cu->len= strlen(textbuf);
+ cu->len= wcslen(textbuf);
memcpy(textbufinfo, str+2+cu->len+1, cu->len*sizeof(CharInfo));
cu->selstart = cu->selend = 0;
@@ -1117,7 +1238,8 @@ static void *editFont_to_undoFont(void)
str= MEM_callocN(MAXTEXT+4+(MAXTEXT+4)*sizeof(CharInfo), "string undo");
- strncpy(str+2, textbuf, MAXTEXT);
+ wcs2utf8s(str, textbuf);
+
*((short *)str)= cu->pos;
memcpy(str+2+cu->len+1, textbufinfo, cu->len*sizeof(CharInfo));
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c
index f914d03562c..c0bd38eb71f 100644
--- a/source/blender/src/interface.c
+++ b/source/blender/src/interface.c
@@ -68,6 +68,8 @@
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_vec_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vfont_types.h"
#include "BKE_blender.h"
#include "BKE_utildefines.h"
@@ -2687,6 +2689,56 @@ static int ui_do_but_HSVCUBE(uiBut *but)
return but->retval;
}
+#ifdef INTERNATIONAL
+
+static int ui_do_but_CHARTAB(uiBut *but)
+{
+ /* Variables */
+ short mval[2];
+ float sx, sy, ex, ey;
+ float width, height;
+ float butw, buth;
+ int x, y;
+ unsigned long cs;
+ unsigned long che;
+
+ /* Check the position */
+ uiGetMouse(mywinget(), mval);
+
+ /* Calculate the size of the button */
+ width = abs(but->x2 - but->x1);
+ height = abs(but->y2 - but->y1);
+
+ butw = floor(width / 12);
+ buth = floor(height / 6);
+
+ /* Initialize variables */
+ sx = but->x1;
+ ex = but->x1 + butw;
+ sy = but->y1 + height - buth;
+ ey = but->y1 + height;
+
+ cs = G.charstart;
+
+ /* And the character is */
+ x = (int) ((mval[0] / butw) - 0.5);
+ y = (int) (6 - ((mval[1] / buth) - 0.5));
+
+ che = cs + (y*12) + x;
+
+ if(che > G.charmax)
+ che = 0;
+
+ if(G.obedit)
+ {
+ do_textedit(0,0,che);
+ }
+
+ return but->retval;
+}
+
+#endif
+
/* ************************************************ */
@@ -2925,6 +2977,12 @@ static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent)
case HSVCUBE:
retval= ui_do_but_HSVCUBE(but);
break;
+
+#ifdef INTERNATIONAL
+ case CHARTAB:
+ retval= ui_do_but_CHARTAB(but);
+ break;
+#endif
}
block->flag &= ~UI_BLOCK_BUSY;
@@ -3383,7 +3441,66 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent)
}
}
break;
+
+
+#ifdef INTERNATIONAL
+ //HACK to let the chartab button react to the mousewheel and PGUP/PGDN keys
+ case WHEELUPMOUSE:
+ case PAGEUPKEY:
+ for(but= block->buttons.first; but; but= but->next)
+ {
+ if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
+ {
+ G.charstart = G.charstart - (12*6);
+ if(G.charstart < 0)
+ G.charstart = 0;
+ if(G.charstart < G.charmin)
+ G.charstart = G.charmin;
+ ui_draw_but(but);
+
+ //Really nasty... to update the num button from the same butblock
+ for(bt= block->buttons.first; bt; bt= bt->next)
+ {
+ if(bt->type == NUM) {
+ ui_check_but(bt);
+ ui_draw_but(bt);
+ }
+ }
+ retval=UI_CONT;
+ break;
+ }
+ }
+ break;
+ case WHEELDOWNMOUSE:
+ case PAGEDOWNKEY:
+ for(but= block->buttons.first; but; but= but->next)
+ {
+ if(but->type == CHARTAB && (but->flag & UI_MOUSE_OVER))
+ {
+ G.charstart = G.charstart + (12*6);
+ if(G.charstart > (0xffff - 12*6))
+ G.charstart = 0xffff - (12*6);
+ if(G.charstart > G.charmax - 12*6)
+ G.charstart = G.charmax - 12*6;
+ ui_draw_but(but);
+
+ for(bt= block->buttons.first; bt; bt= bt->next)
+ {
+ if(bt->type == NUM) {
+ ui_check_but(bt);
+ ui_draw_but(bt);
+ }
+ }
+
+ but->flag |= UI_ACTIVE;
+ retval=UI_RETURN_OK;
+ break;
+ }
+ }
+ break;
+#endif
+
case PADENTER:
case RETKEY: // prevent treating this as mousemove. for example when you enter at popup
if(block->flag & UI_BLOCK_LOOP) break;
diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c
index 92f38cbd1e8..4d933abab69 100644
--- a/source/blender/src/interface_draw.c
+++ b/source/blender/src/interface_draw.c
@@ -1,3 +1,4 @@
+
/**
* $Id$
*
@@ -58,6 +59,8 @@
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_vec_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_packedFile_types.h"
#include "BKE_blender.h"
#include "BKE_utildefines.h"
@@ -79,6 +82,8 @@
#include "BSE_view.h"
+#include "FTF_Api.h"
+
#include "mydevice.h"
#include "interface.h"
#include "blendef.h"
@@ -1698,6 +1703,129 @@ static void ui_draw_but_HSVCUBE(uiBut *but)
fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
}
+#ifdef INTERNATIONAL
+static void ui_draw_but_CHARTAB(uiBut *but)
+{
+ /* Some local variables */
+ float sx, sy, ex, ey;
+ float width, height;
+ float butw, buth;
+ int x, y;
+ unsigned long cs;
+ wchar_t wstr[2];
+ unsigned char ustr[16];
+ PackedFile *pf;
+
+ /* Calculate the size of the button */
+ width = abs(but->x2 - but->x1);
+ height = abs(but->y2 - but->y1);
+
+ butw = floor(width / 12);
+ buth = floor(height / 6);
+
+ /* Initialize variables */
+ sx = but->x1;
+ ex = but->x1 + butw;
+ sy = but->y1 + height - buth;
+ ey = but->y1 + height;
+
+ cs = G.charstart;
+
+ /* Set the font */
+ if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+ {
+ char tmpStr[256];
+
+ // Is the font file packed, if so then use the packed file
+ if(G.selfont->packedfile)
+ {
+ pf = G.selfont->packedfile;
+ FTF_SetFont(pf->data, pf->size, 14.0);
+ }
+ else
+ {
+ int err;
+
+ strcpy(tmpStr, G.selfont->name);
+ BLI_convertstringcode(tmpStr, G.sce, 0);
+ err = FTF_SetFont(tmpStr, 0, 14.0);
+ }
+ }
+
+ /* Start drawing the button itself */
+ glShadeModel(GL_SMOOTH);
+
+ glColor3ub(200, 200, 200);
+ glRectf((but->x1), (but->y1), (but->x2), (but->y2));
+
+ glColor3ub(0, 0, 0);
+ for(y = 0; y < 6; y++)
+ {
+ // Do not draw more than the category allows
+ if(cs > G.charmax) break;
+
+ for(x = 0; x < 12; x++)
+ {
+ // Do not draw more than the category allows
+ if(cs > G.charmax) break;
+
+ // Draw one grid cell
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(sx, sy);
+ glVertex2f(ex, sy);
+ glVertex2f(ex, ey);
+ glVertex2f(sx, ey);
+ glEnd();
+
+ // Draw character inside the cell
+ memset(wstr, 0, sizeof(wchar_t)*2);
+ memset(ustr, 0, 16);
+
+ wstr[0] = cs;
+ wcs2utf8s(ustr, wstr);
+
+ if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
+ {
+ float wid;
+ float llx, lly, llz, urx, ury, urz;
+ float dx, dy;
+ float px, py;
+
+ // Calculate the position
+ wid = FTF_GetStringWidth(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ FTF_GetBoundingBox(ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ dx = urx-llx;
+ dy = ury-lly;
+
+ // This isn't fully functional since the but->aspect isn't working like I suspected
+ px = sx + ((butw/but->aspect)-dx)/2;
+ py = sy + ((buth/but->aspect)-dy)/2;
+
+ // Set the position and draw the character
+ ui_rasterpos_safe(px, py, but->aspect);
+ FTF_DrawString(ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
+ }
+ else
+ {
+ ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
+ BIF_DrawString(but->font, ustr, 0);
+ }
+
+ // Calculate the next position and character
+ sx += butw; ex +=butw;
+ cs++;
+ }
+ /* Add the y position and reset x position */
+ sy -= buth;
+ ey -= buth;
+ sx = but->x1;
+ ex = but->x1 + butw;
+ }
+ glShadeModel(GL_FLAT);
+}
+
+#endif // INTERNATIONAL
+
static void ui_draw_roundbox(uiBut *but)
{
BIF_ThemeColorShade(but->themecol, but->a2);
@@ -1754,7 +1882,6 @@ void ui_set_embossfunc(uiBut *but, int drawtype)
// note: if you want aligning, adapt the call uiBlockEndAlign in interface.c
}
-
void ui_draw_but(uiBut *but)
{
double value;
@@ -1796,6 +1923,13 @@ void ui_draw_but(uiBut *but)
ui_draw_but_HSVCUBE(but); // box for colorpicker, three types
break;
+#ifdef INTERNATIONAL
+ case CHARTAB:
+ value= ui_get_but_val(but);
+ ui_draw_but_CHARTAB(but);
+ break;
+#endif
+
case LINK:
case INLINK:
ui_draw_icon(but, but->icon);
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
index 56cb25b5c55..d5b35bdff60 100644
--- a/source/blender/src/usiblender.c
+++ b/source/blender/src/usiblender.c
@@ -78,6 +78,8 @@
#include "BKE_packedFile.h"
#include "BKE_utildefines.h"
+#include "BLI_vfontdata.h"
+
#include "BIF_fsmenu.h"
#include "BIF_gl.h"
#include "BIF_interface.h"
@@ -291,9 +293,20 @@ int BIF_read_homefile(void)
char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
char *home= BLI_gethome();
int success;
+ struct TmpFont *tf;
BLI_clean(home);
+ tf= G.ttfdata.first;
+ while(tf)
+ {
+ freePackedFile(tf->pf);
+ tf->pf = NULL;
+ tf->vfont = NULL;
+ tf= tf->next;
+ }
+ BLI_freelistN(&G.ttfdata);
+
#if 0
//#ifdef _WIN32 // FULLSCREEN
static int screenmode = -1;
@@ -632,6 +645,17 @@ extern ListBase editelems;
void exit_usiblender(void)
{
+ struct TmpFont *tf;
+ tf= G.ttfdata.first;
+ while(tf)
+ {
+ freePackedFile(tf->pf);
+ tf->pf= NULL;
+ tf->vfont= NULL;
+ tf= tf->next;
+ }
+ BLI_freelistN(&G.ttfdata);
+
freeAllRad();
BKE_freecubetable();