forked from bartvdbraak/blender
On behalf of Mika Saari, the famous Unicode Font support!
Further information is available here: http://wiki.blender.org/bin/view.pl/Blenderdev/UnicodeFont3D Shortlist of features: - Unicode character support for Font3D - UI to select characters from Unicode character list - UI to select Unicode table areas - Optimized character loading (Load only those characters which are used in font object) Please test extensively if it breaks anything, try also loading/saving files, packing fonts, etc. The official text regression file in the regression suite should be a good start. Thanks to mikasaari for this very useful addition!
This commit is contained in:
parent
2cb24cefb2
commit
98bd4615b5
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -217,6 +217,10 @@ void initglobals(void)
|
||||
#endif
|
||||
|
||||
clear_workob(); /* object.c */
|
||||
|
||||
G.charstart = 0x0000;
|
||||
G.charmin = 0x0000;
|
||||
G.charmax = 0xffff;
|
||||
}
|
||||
|
||||
/***/
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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_Face face;
|
||||
FT_GlyphSlot glyph;
|
||||
FT_UInt glyph_index;
|
||||
FT_Outline ftoutline;
|
||||
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_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);
|
||||
// Extract the first 256 character from TTF
|
||||
lcode= charcode= FT_Get_First_Char(face, &glyph_index);
|
||||
|
||||
if(height != 0.0)
|
||||
scale = 1.0 / height;
|
||||
else
|
||||
scale = 1.0 / 1000.0;
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
|
||||
//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++;
|
||||
}
|
||||
|
||||
//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++;
|
||||
}
|
||||
}
|
||||
for ( n = 0; n < face->num_charmaps; n++ )
|
||||
{
|
||||
charmap = face->charmaps[n];
|
||||
if (charmap->encoding == FT_ENCODING_APPLE_ROMAN)
|
||||
{
|
||||
found = charmap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(npoints) MEM_freeN(npoints);
|
||||
if(onpoints) MEM_freeN(onpoints);
|
||||
err = FT_Set_Charmap( face, found );
|
||||
|
||||
if( err )
|
||||
return NULL;
|
||||
|
||||
lcode= charcode= FT_Get_First_Char(face, &glyph_index);
|
||||
}
|
||||
return vfd;
|
||||
|
||||
// Load characters
|
||||
while(charcode < 256)
|
||||
{
|
||||
// Generate the font data
|
||||
freetypechar_to_vchar(face, charcode, vfd);
|
||||
|
||||
// Next glyph
|
||||
charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
|
||||
|
||||
// Check that we won't start infinite loop
|
||||
if(charcode <= lcode)
|
||||
break;
|
||||
lcode = charcode;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
void do_textedit(unsigned short event, short val, char _ascii);
|
||||
typedef struct unicodect
|
||||
{
|
||||
char *name;
|
||||
char *longname;
|
||||
int start;
|
||||
int end;
|
||||
} unicodect;
|
||||
|
||||
void do_textedit(unsigned short event, short val, unsigned long _ascii);
|
||||
void make_editText(void);
|
||||
void load_editText(void);
|
||||
void remake_editText(void);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
while (!feof(fp)) {
|
||||
c = fgetc(fp);
|
||||
if (c!=EOF) insert_into_textbuf(OBACT->data, c);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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));
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user