Initial commit for new text object.

Important notes:

 - Full compatibility with old text objects not fully restored
   (word spacing will be 0.0, need to set it manually to 1.0), will
   either need version upgrade to 238 or a hack. Will check.

 - lorem.c (about to be committed) contains BF copyright notice, but as
   BF did not exist a few hundred years ago, probably best to remove it :)

 - If you notice any cross-platform issues (especially beloved windows),
   please report

 - A few tiny warnings left, I will fix those issues still.

The rest has been said already - so have fun testing. And please do!

=== Reminder:
=== Documentation at http://blender.instinctive.de/docs/textobject.txt ===
This commit is contained in:
Alexander Ewering 2005-06-17 21:04:27 +00:00
parent 9ee2a1ee09
commit 97df61a7e5
20 changed files with 1031 additions and 179 deletions

@ -127,6 +127,8 @@ typedef struct DispList {
float *verts, *nors;
int *index;
unsigned int *col1, *col2;
int charidx;
int pad;
} DispList;
extern void copy_displist(struct ListBase *lbn, struct ListBase *lb);

@ -39,13 +39,22 @@ struct Object;
struct Curve;
struct objfnt;
typedef struct SelBox {
float x, y, w, h;
} SelBox;
void BKE_font_register_builtin(void *mem, int size);
void free_vfont(struct VFont *sc);
struct VFont *load_vfont(char *name);
struct chartrans *text_to_curve(struct Object *ob, int mode);
int style_to_sel(void);
int mat_to_sel(void);
void font_duplilist(struct Object *par);
struct SelBox *selboxes;
int getselection(int *start, int *end);
#endif

@ -145,8 +145,10 @@ void free_curve(Curve *cu)
if(cu->mat) MEM_freeN(cu->mat);
if(cu->str) MEM_freeN(cu->str);
if(cu->strinfo) MEM_freeN(cu->strinfo);
if(cu->bb) MEM_freeN(cu->bb);
if(cu->path) free_path(cu->path);
if(cu->tb) MEM_freeN(cu->tb);
}
Curve *add_curve(int type)
@ -165,6 +167,7 @@ Curve *add_curve(int type)
cu->pathlen= 100;
cu->resolu= cu->resolv= 6;
cu->width= 1.0;
cu->wordspace = 1.0;
cu->spacing= cu->linedist= 1.0;
cu->fsize= 1.0;
cu->texflag= CU_AUTOSPACE;
@ -189,6 +192,8 @@ Curve *copy_curve(Curve *cu)
}
cun->str= MEM_dupallocN(cu->str);
cun->strinfo= MEM_dupallocN(cu->strinfo);
cun->tb= MEM_dupallocN(cu->tb);
cun->bb= MEM_dupallocN(cu->bb);
cun->key= copy_key(cu->key);
@ -202,6 +207,9 @@ Curve *copy_curve(Curve *cu)
if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
id_us_plus((ID *)cun->vfont);
id_us_plus((ID *)cun->vfontb);
id_us_plus((ID *)cun->vfonti);
id_us_plus((ID *)cun->vfontbi);
return cun;
}

@ -1272,6 +1272,7 @@ static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
dl->parts= 1;
dl->nr= len;
dl->col= nu->mat_nr;
dl->charidx= nu->charidx;
data= dl->verts;
@ -1359,12 +1360,17 @@ void filldisplist(ListBase *dispbase, ListBase *to)
EditFace *efa;
DispList *dlnew=0, *dl;
float *f1;
int colnr=0, cont=1, tot, a, *index;
int colnr=0, charidx=0, cont=1, tot, a, *index;
long totvert;
if(dispbase==0) return;
if(dispbase->first==0) return;
/* tijd= clock(); */
/* bit-wise and comes after == .... so this doesn't work... */
/* if(G.f & G_PLAYANIM == 0) waitcursor(1); */
if( !(G.f & G_PLAYANIM) ) waitcursor(1);
while(cont) {
cont= 0;
totvert=0;
@ -1373,10 +1379,11 @@ void filldisplist(ListBase *dispbase, ListBase *to)
while(dl) {
if(dl->type==DL_POLY) {
if(colnr<dl->col) cont= 1;
else if(colnr==dl->col) {
if(charidx<dl->charidx) cont= 1;
else if(charidx==dl->charidx) {
colnr= dl->col;
charidx= dl->charidx;
/* make editverts and edges */
f1= dl->verts;
@ -1464,10 +1471,16 @@ void filldisplist(ListBase *dispbase, ListBase *to)
}
BLI_end_edgefill();
colnr++;
charidx++;
}
/* do not free polys, needed for wireframe display */
/* same as above ... */
/* if(G.f & G_PLAYANIM == 0) waitcursor(0); */
if( !(G.f & G_PLAYANIM) ) waitcursor(0);
/* printf("time: %d\n",(clock()-tijd)/1000); */
}
static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)

@ -69,11 +69,15 @@
#include "BKE_curve.h"
#include "BKE_displist.h"
#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
struct SelBox *selboxes= NULL;
struct chartrans {
float xof, yof;
float rot;
short linenr,charnr;
char dobreak;
};
void free_vfont(struct VFont *vf)
@ -215,17 +219,40 @@ VFont *load_vfont(char *name)
return vfont;
}
static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, float rot)
static VFont *which_vfont(Curve *cu, CharInfo *info)
{
switch(info->flag & CU_STYLE) {
case CU_BOLD:
return(cu->vfontb);
case CU_ITALIC:
return(cu->vfonti);
case (CU_BOLD|CU_ITALIC):
return(cu->vfontbi);
default:
return(cu->vfont);
}
}
static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx, float ofsy, float rot, int charidx)
{
BezTriple *bezt1, *bezt2;
Nurb *nu1, *nu2;
float *fp, fsize, shear, x, si, co;
VFontData *vfd;
int i;
int i, sel=0;
vfd= vfont_get_data(cu->vfont);
vfd= vfont_get_data(which_vfont(cu, info));
if (!vfd) return;
if (cu->selend < cu->selstart) {
if ((charidx >= (cu->selend)) && (charidx <= (cu->selstart-2)))
sel= 1;
}
else {
if ((charidx >= (cu->selstart-1)) && (charidx <= (cu->selend-1)))
sel= 1;
}
/* make a copy at distance ofsx,ofsy with shear*/
fsize= cu->fsize;
shear= cu->shear;
@ -244,6 +271,8 @@ static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, fl
nu2->bp = 0;
nu2->knotsu = nu2->knotsv = 0;
nu2->flag= CU_SMOOTH;
nu2->charidx = charidx;
if (info->mat_nr) nu2->mat_nr= info->mat_nr-1;
/* nu2->trim.first = 0; */
/* nu2->trim.last = 0; */
i = nu2->pntsu;
@ -300,23 +329,52 @@ static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, fl
BLI_addtail(&(cu->nurb), nu2);
}
nu1 = nu1->next;
}
}
int getselection(int *start, int *end)
{
Curve *cu;
if (G.obedit==NULL || G.obedit->type != OB_FONT) return 0;
cu= G.obedit->data;
if (cu->selstart == 0) return 0;
if (cu->selstart <= cu->selend) {
*start = cu->selstart-1;
*end = cu->selend-1;
return 1;
}
else {
*start = cu->selend;
*end = cu->selstart-2;
return -1;
}
}
struct chartrans *text_to_curve(Object *ob, int mode)
{
VFont *vfont;
VFont *vfont, *oldvfont;
VFontData *vfd;
Curve *cu, *cucu;
struct chartrans *chartransdata, *ct;
float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy;
float cmat[3][3], timeofs, si, co, sizefac;
float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2;
int i, slen, oldflag;
float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3;
int i, slen, oldflag, j;
short cnr=0, lnr=0;
char ascii, *mem;
int outta;
float vecyo[3];
CharInfo *info;
float wsfac;
TextBox *tb;
int curbox;
int selstart, selend;
SelBox *sb;
/* renark: do calculations including the trailing '\0' of a string
because the cursor can be at that location */
@ -324,54 +382,101 @@ struct chartrans *text_to_curve(Object *ob, int mode)
if(ob->type!=OB_FONT) return 0;
cu= ob->data;
vfont= cu->vfont;
if (vfont==0) return 0;
if (cu->str==0) return 0;
vfd= vfont_get_data(vfont);
if (!vfd) return 0;
/* count number of lines */
mem= cu->str;
slen = strlen(mem);
cu->lines= 1;
for (i= 0; i<=slen; i++, mem++) {
ascii = *mem;
if(ascii== '\n' || ascii== '\r') cu->lines++;
if (cu->str==0) return 0;
if (cu->strinfo==NULL) { /* old file */
fprintf(stderr, "old file\n");
cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat");
}
/* calc offset and rotation of each char */
ct = chartransdata =
(struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");
linedata= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
linedata2= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2");
xof= cu->xof;
yof= cu->yof;
xtrax= 0.5f*cu->spacing-0.5f;
/* We assume the worst case: 1 character per line (is freed at end anyway) */
linedata= MEM_mallocN(sizeof(float)*(slen+2),"buildtext2");
linedata2= MEM_mallocN(sizeof(float)*(slen+2),"buildtext3");
linedata3= MEM_mallocN(sizeof(float)*(slen+2),"buildtext4");
linedist= cu->linedist;
xof= cu->xof + (cu->tb[0].x/cu->fsize);
yof= cu->yof + (cu->tb[0].y/cu->fsize);
xtrax= 0.5f*cu->spacing-0.5f;
oldvfont = NULL;
for (i=0; i<slen; i++) cu->strinfo[i].flag &= ~CU_WRAP;
if (selboxes) MEM_freeN(selboxes);
selboxes = NULL;
if (getselection(&selstart, &selend))
selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");
tb = &(cu->tb[0]);
curbox= 0;
for (i = 0 ; i<=slen ; i++) {
makebreak:
ascii = cu->str[i];
if(ascii== '\n' || ascii== '\r' || ascii==0) {
info = &(cu->strinfo[i]);
vfont = which_vfont(cu, info);
if (vfont==0) return 0;
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]==' ') {
ct -= (i-(j-1));
cnr -= (i-(j-1));
i = j-1;
xof = ct->xof;
ct[1].dobreak = 1;
cu->strinfo[i+1].flag |= CU_WRAP;
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]);
ct->dobreak= 1;
cu->strinfo[i+1].flag |= CU_WRAP;
ct -= 1;
cnr -= 1;
i--;
xof = ct->xof;
goto makebreak;
}
}
}
if(ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
ct->xof= xof;
ct->yof= yof;
ct->linenr= lnr;
ct->charnr= cnr;
/* only empty lines are allowed smaller than 1 */
// if( linedist<1.0) {
// if(i<slen && (cu->str[i+1]=='\r' || cu->str[i+1]=='\n')) yof-= linedist;
// else yof-= 1.0;
// }
// else
yof-= linedist;
maxlen= MAX2(maxlen, xof);
linedata[lnr]= xof;
maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize));
linedata[lnr]= xof-tb->x/cu->fsize;
linedata2[lnr]= cnr;
xof= cu->xof;
linedata3[lnr]= tb->w/cu->fsize;
if ( (tb->h != 0.0) &&
((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize))) &&
(cu->totbox > (curbox+1)) ) {
maxlen= 0;
tb++;
curbox++;
yof= cu->yof + tb->y/cu->fsize;
}
xof= cu->xof + (tb->x/cu->fsize);
lnr++;
cnr= 0;
}
@ -391,51 +496,45 @@ struct chartrans *text_to_curve(Object *ob, int mode)
ct->linenr= lnr;
ct->charnr= cnr++;
xof += vfd->width[ascii] + xtrax;
if (selboxes && (i>=selstart) && (i<=selend)) {
sb = &(selboxes[i-selstart]);
sb->y = yof*cu->fsize-linedist*cu->fsize*0.1;
sb->h = linedist*cu->fsize;
sb->w = xof*cu->fsize;
}
if (ascii==32) wsfac = cu->wordspace; else wsfac = 1.0;
xof += (vfd->width[ascii]*wsfac*(1.0+(info->kern/20.0)) ) + xtrax;
if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w;
}
ct++;
}
/* met alle fontsettings plekken letters berekenen */
if(cu->spacemode!=CU_LEFT/* && lnr>1*/) {
ct= chartransdata;
if(cu->spacemode==CU_RIGHT) {
for(i=0;i<lnr;i++) linedata[i]= -linedata[i];
for (i=0; i<=slen; i++) {
ct->xof+= linedata[ct->linenr];
ct++;
}
} else if(cu->spacemode==CU_MIDDLE) {
for(i=0;i<lnr;i++) linedata[i]= -linedata[i]/2;
for (i=0; i<=slen; i++) {
ct->xof+= linedata[ct->linenr];
ct++;
}
} else if(cu->spacemode==CU_FLUSH) {
for(i=0;i<lnr;i++)
if(linedata2[i]>1)
linedata[i]= ((maxlen-linedata[i])/(linedata2[i]-1));
for (i=0; i<=slen; i++) {
ct->xof+= (ct->charnr*linedata[ct->linenr])-maxlen/2;
ct++;
}
}
cu->lines= 1;
ct= chartransdata;
for (i= 0; i<=slen; i++, mem++, ct++) {
ascii = *mem;
if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
}
/* old alignment here, to spot the differences */
/*
// linedata is now: width of line
// linedata2 is now: number of characters
// linedata3 is now: maxlen of that line
if(cu->spacemode!=CU_LEFT && lnr>1) {
ct= chartransdata;
if(cu->spacemode==CU_RIGHT) {
for(i=0;i<lnr;i++) linedata[i]= maxlen-linedata[i];
for(i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i];
for (i=0; i<=slen; i++) {
ct->xof+= linedata[ct->linenr];
ct++;
}
} else if(cu->spacemode==CU_MIDDLE) {
for(i=0;i<lnr;i++) linedata[i]= (maxlen-linedata[i])/2;
for(i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2;
for (i=0; i<=slen; i++) {
ct->xof+= linedata[ct->linenr];
ct++;
@ -443,14 +542,18 @@ struct chartrans *text_to_curve(Object *ob, int mode)
} else if(cu->spacemode==CU_FLUSH) {
for(i=0;i<lnr;i++)
if(linedata2[i]>1)
linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1);
linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
for (i=0; i<=slen; i++) {
ct->xof+= ct->charnr*linedata[ct->linenr];
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')) {
ct->xof+= ct->charnr*linedata[ct->linenr];
}
ct++;
}
}
}
*/
/* TEXT ON CURVE */
if(cu->textoncurve) {
cucu= cu->textoncurve->data;
@ -533,17 +636,29 @@ struct chartrans *text_to_curve(Object *ob, int mode)
}
}
if (selboxes) {
ct= chartransdata;
for (i=0; i<=selend; i++, ct++) {
if (i>=selstart) {
selboxes[i-selstart].x = ct->xof*cu->fsize;
}
}
}
if(mode==FO_CURSUP || mode==FO_CURSDOWN) {
if(mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) {
/* 2: curs up
3: curs down */
ct= chartransdata+cu->pos;
if(mode==FO_CURSUP && ct->linenr==0);
else if(mode==FO_CURSDOWN && ct->linenr==lnr);
if((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0);
else if((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr);
else {
if(mode==FO_CURSUP) lnr= ct->linenr-1;
else lnr= ct->linenr+1;
switch(mode) {
case FO_CURSUP: lnr= ct->linenr-1; break;
case FO_CURSDOWN: lnr= ct->linenr+1; break;
case FO_PAGEUP: lnr= ct->linenr-10; break;
case FO_PAGEDOWN: lnr= ct->linenr+10; break;
}
cnr= ct->charnr;
/* seek for char with lnr en cnr */
cu->pos= 0;
@ -582,21 +697,55 @@ struct chartrans *text_to_curve(Object *ob, int mode)
}
if (mode == FO_SELCHANGE) {
MEM_freeN(chartransdata);
MEM_freeN(linedata);
MEM_freeN(linedata2);
MEM_freeN(linedata3);
return NULL;
}
if(mode==0) {
/* make nurbdata */
freeNurblist(&cu->nurb);
ct= chartransdata;
for (i= 0; i<slen; i++) {
ascii = cu->str[i];
buildchar(cu, ascii, ct->xof, ct->yof, ct->rot);
ct++;
if (cu->sepchar==0) {
for (i= 0; i<slen; i++) {
ascii = cu->str[i];
info = &(cu->strinfo[i]);
buildchar(cu, ascii, info, ct->xof, ct->yof, ct->rot, i);
ct++;
}
}
else {
outta = 0;
for (i= 0; (i<slen) && (outta==0); i++) {
ascii = cu->str[i];
info = &(cu->strinfo[i]);
if (cu->sepchar == (i+1)) {
cu->str[0] = ascii;
cu->str[1] = 0;
cu->strinfo[0]= *info;
cu->pos = 1;
cu->len = 1;
vecyo[0] = ct->xof;
vecyo[1] = ct->yof;
vecyo[2] = 0;
Mat4MulVecfl(ob->obmat, vecyo);
VECCOPY(ob->loc, vecyo);
outta = 1;
cu->sepchar = 0;
}
ct++;
}
}
}
MEM_freeN(linedata);
MEM_freeN(linedata2);
MEM_freeN(linedata3);
if(mode==FO_DUPLI) {
return chartransdata;

@ -119,8 +119,8 @@ typedef struct pschar {
#define NOTHEX (100)
#define MC1 52845
#define MC2 22719
#define MAXSUBRS 1000
#define MAXCHARS 1000
#define MAXSUBRS 4000
#define MAXCHARS 4000
#define MAXTRIES 30
/* some local thingies */
@ -215,7 +215,7 @@ static unsigned short int mr;
static char *bindat;
static int datbytes;
static int firsted;
static short chardata[2000];
static short chardata[20000];
static int nshorts;
static int thecharwidth, thesidebearing;
@ -763,10 +763,12 @@ static int decryptprogram(char *buf, int len)
resetdecrypt(4330);
for(i=0; i<len; i++) {
if(i<SKIP)
if(i<SKIP) {
mdecrypt(buf[i]);
else
}
else {
buf[i-SKIP] = mdecrypt(buf[i]);
}
}
return len-SKIP;
}
@ -1447,10 +1449,10 @@ static void spline_line(float x0, float y0, float x1, float y1)
static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
applymat(mat,&x0,&y0);
applymat(mat,&x1,&y1);
applymat(mat,&x2,&y2);
applymat(mat,&x3,&y3);
if(sp_npnts == 0) {
chardata[nshorts++] = SP_MOVETO;
chardata[nshorts++] = floor(x0);

@ -1888,6 +1888,9 @@ static void lib_link_curve(FileData *fd, Main *main)
cu->taperobj= newlibadr(fd, cu->id.lib, cu->taperobj);
cu->textoncurve= newlibadr(fd, cu->id.lib, cu->textoncurve);
cu->vfont= newlibadr_us(fd, cu->id.lib, cu->vfont);
cu->vfontb= newlibadr_us(fd, cu->id.lib, cu->vfontb);
cu->vfonti= newlibadr_us(fd, cu->id.lib, cu->vfonti);
cu->vfontbi= newlibadr_us(fd, cu->id.lib, cu->vfontbi);
cu->ipo= newlibadr_us(fd, cu->id.lib, cu->ipo);
cu->key= newlibadr_us(fd, cu->id.lib, cu->key);
@ -1920,6 +1923,7 @@ static void switch_endian_knots(Nurb *nu)
static void direct_link_curve(FileData *fd, Curve *cu)
{
Nurb *nu;
TextBox *tb;
cu->mat= newdataadr(fd, cu->mat);
test_pointer_array(fd, (void **)&cu->mat);
@ -1928,6 +1932,19 @@ static void direct_link_curve(FileData *fd, Curve *cu)
if(cu->vfont==0) link_list(fd, &(cu->nurb));
else {
cu->nurb.first=cu->nurb.last= 0;
cu->strinfo= newdataadr(fd, cu->strinfo);
cu->tb= newdataadr(fd, cu->tb);
tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBoxread");
if (cu->tb) {
memcpy(tb, cu->tb, cu->totbox*sizeof(TextBox));
MEM_freeN(cu->tb);
cu->tb= tb;
} else {
cu->totbox = 1;
cu->actbox = 1;
cu->tb = tb;
cu->tb[0].w = cu->linewidth;
}
}
cu->bev.first=cu->bev.last= 0;
@ -5018,6 +5035,9 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
expand_doit(fd, mainvar, cu->mat[a]);
}
expand_doit(fd, mainvar, cu->vfont);
expand_doit(fd, mainvar, cu->vfontb);
expand_doit(fd, mainvar, cu->vfonti);
expand_doit(fd, mainvar, cu->vfontbi);
expand_doit(fd, mainvar, cu->key);
expand_doit(fd, mainvar, cu->ipo);
expand_doit(fd, mainvar, cu->bevobj);

@ -850,6 +850,8 @@ static void write_curves(WriteData *wd, ListBase *idbase)
if(cu->vfont) {
writedata(wd, DATA, cu->len+1, cu->str);
writestruct(wd, DATA, "CharInfo", cu->len, cu->strinfo);
writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);
}
else {
/* is also the order of reading */

@ -35,6 +35,8 @@
struct Text;
char *BIF_lorem;
void do_textedit(unsigned short event, short val, char _ascii);
void make_editText(void);
void load_editText(void);
@ -44,6 +46,9 @@ void paste_editText(void);
void txt_export_to_object(struct Text *text);
void txt_export_to_objects(struct Text *text);
void undo_push_font(char *);
void load_3dtext_fs(char *);
void add_lorem(void);
void text_makedisplist(struct Object *ob);
/**
* @attention The argument is discarded. It is there for

@ -193,6 +193,9 @@ void bglEnd(void);
void bglVertex3fv(float *vec);
void bglVertex2fv(float *vec);
void set_inverted_drawing(int enable);
/* own working polygon offset */
void bglPolygonOffset(float dist);

@ -317,7 +317,7 @@ enum {
#define B_DOCENTRECURSOR 2017
/* 32 values! */
#define B_OBLAY 2018
#define B_OBLAY 2019
#define B_MESHBUTS 2100
@ -397,6 +397,12 @@ enum {
#define B_LOADFONT 2204
#define B_TEXTONCURVE 2205
#define B_PACKFONT 2206
#define B_LOAD3DTEXT 2207
#define B_LOREM 2208
#define B_FASTFONT 2209
#define B_INSTB 2210
#define B_DELTB 2211
#define B_STYLETOSEL 2212
/* *********************** */
#define B_IKABUTS 2400

@ -40,6 +40,8 @@
#include "DNA_vec_types.h"
#include "DNA_ID.h"
#define MAXTEXTBOX 256 /* used in readfile.c and editfont.c */
struct BoundBox;
struct Object;
struct Ipo;
@ -101,8 +103,21 @@ typedef struct Nurb {
BPoint *bp;
BezTriple *bezt;
int charidx;
int pad;
} Nurb;
typedef struct CharInfo {
short kern;
short mat_nr;
char flag;
char pad;
short pad2;
} CharInfo;
typedef struct TextBox {
float x, y, w, h;
} TextBox;
typedef struct Curve {
ID id;
@ -135,12 +150,26 @@ typedef struct Curve {
/* font part */
short len, lines, pos, spacemode;
float spacing, linedist, shear, fsize;
float spacing, linedist, shear, fsize, wordspace;
float xof, yof;
float linewidth;
char *str, family[24];
char *str;
char family[24];
struct VFont *vfont;
struct VFont *vfontb;
struct VFont *vfonti;
struct VFont *vfontbi;
int sepchar;
int totbox, actbox, pad;
struct TextBox *tb;
int selstart, selend;
struct CharInfo *strinfo;
struct CharInfo curinfo;
} Curve;
typedef struct IpoCurve {
@ -177,6 +206,7 @@ typedef struct IpoCurve {
#define CU_NOPUNOFLIP 64
#define CU_STRETCH 128
#define CU_OFFS_PATHDIST 256
#define CU_FAST 512 /* Font: no filling inside editmode */
/* spacemode */
#define CU_LEFT 0
@ -204,5 +234,16 @@ typedef struct IpoCurve {
#define HD_VECT 2
#define HD_ALIGN 3
/* *************** CHARINFO **************** */
/* flag */
#define CU_STYLE (1+2)
#define CU_BOLD 1
#define CU_ITALIC 2
#define CU_UNDERLINE 4
#define CU_WRAP 8 /* wordwrap occured here */
#endif

@ -55,6 +55,9 @@ typedef struct VFont {
#define FO_CURSUP 2
#define FO_CURSDOWN 3
#define FO_DUPLI 4
#define FO_PAGEUP 8
#define FO_PAGEDOWN 9
#define FO_SELCHANGE 10
#endif

@ -479,6 +479,13 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
nu= nu->next;
}
}
else if (G.obedit->type == OB_FONT) {
if (mat_to_sel()) {
text_to_curve(G.obedit, 0);
text_makedisplist(G.obedit);
allqueue(REDRAWVIEW3D, 0);
}
}
allqueue(REDRAWVIEW3D_Z, 0);
makeDispList(G.obedit);
BIF_undo_push("Assign material index");
@ -841,8 +848,24 @@ static void load_buts_vfont(char *name)
}
else id_us_plus((ID *)vf);
if(cu->vfont) cu->vfont->id.us--;
cu->vfont= vf;
switch(cu->curinfo.flag & CU_STYLE) {
case CU_BOLD:
if(cu->vfontb) cu->vfontb->id.us--;
cu->vfontb= vf;
break;
case CU_ITALIC:
if(cu->vfonti) cu->vfonti->id.us--;
cu->vfonti= vf;
break;
case (CU_BOLD|CU_ITALIC):
if(cu->vfontbi) cu->vfontbi->id.us--;
cu->vfontbi= vf;
break;
default:
if(cu->vfont) cu->vfont->id.us--;
cu->vfont= vf;
break;
}
text_to_curve(OBACT, 0);
makeDispList(OBACT);
@ -858,6 +881,7 @@ void do_fontbuts(unsigned short event)
Object *ob;
ScrArea *sa;
char str[80];
int i;
ob= OBACT;
@ -867,6 +891,51 @@ void do_fontbuts(unsigned short event)
makeDispList(ob);
allqueue(REDRAWVIEW3D, 0);
break;
case B_STYLETOSEL:
if (style_to_sel()) {
text_to_curve(ob, 0);
text_makedisplist(ob);
allqueue(REDRAWVIEW3D, 0);
}
allqueue(REDRAWBUTSEDIT, 0);
break;
case B_FASTFONT:
if (G.obedit) {
cu= G.obedit->data;
cu->flag ^= CU_FAST;
error("Not in editmode!");
}
break;
case B_INSTB:
cu= ob->data;
if (cu->totbox < 256) {
for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
cu->actbox++;
cu->totbox++;
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
text_to_curve(ob, 0);
makeDispList(ob);
}
else {
error("Do you really need that many text frames?");
}
break;
case B_DELTB:
cu= ob->data;
if (cu->totbox > 1) {
for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
cu->totbox--;
cu->actbox--;
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
text_to_curve(ob, 0);
makeDispList(ob);
}
break;
case B_TOUPPER:
to_upper();
break;
@ -908,6 +977,19 @@ void do_fontbuts(unsigned short event)
allqueue(REDRAWBUTSEDIT, 0);
break;
case B_LOAD3DTEXT:
if (!G.obedit) { error("Only in editmode!"); return; }
if (G.obedit->type != OB_FONT) return;
activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
break;
case B_LOREM:
if (!G.obedit) { error("Only in editmode!"); return; }
if (G.obedit->type != OB_FONT) return;
add_lorem();
break;
case B_SETFONT:
if(ob) {
cu= ob->data;
@ -915,8 +997,24 @@ void do_fontbuts(unsigned short event)
vf= give_vfontpointer(G.buts->texnr);
if(vf) {
id_us_plus((ID *)vf);
cu->vfont->id.us--;
cu->vfont= vf;
switch(cu->curinfo.flag & CU_STYLE) {
case CU_BOLD:
cu->vfontb->id.us--;
cu->vfontb= vf;
break;
case CU_ITALIC:
cu->vfonti->id.us--;
cu->vfonti= vf;
break;
case (CU_BOLD|CU_ITALIC):
cu->vfontbi->id.us--;
cu->vfontbi= vf;
break;
default:
cu->vfont->id.us--;
cu->vfont= vf;
break;
}
text_to_curve(ob, 0);
makeDispList(ob);
BIF_undo_push("Set vector font");
@ -944,14 +1042,28 @@ static void editing_panel_font_type(Object *ob, Curve *cu)
uiBlock *block;
char *strp;
static int packdummy = 0;
VFontData *vfd;
char str[32];
block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 318, 204)==0) return;
if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
switch(cu->curinfo.flag & CU_STYLE) {
case CU_BOLD:
G.buts->texnr= give_vfontnr(cu->vfontb);
break;
case CU_ITALIC:
G.buts->texnr= give_vfontnr(cu->vfonti);
break;
case (CU_BOLD|CU_ITALIC):
G.buts->texnr= give_vfontnr(cu->vfontbi);
break;
default:
G.buts->texnr= give_vfontnr(cu->vfont);
break;
}
G.buts->texnr= give_vfontnr(cu->vfont);
strp= give_vfontbutstr();
vfd= cu->vfont->data;
// vfd= cu->vfont->data;
uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
@ -962,7 +1074,16 @@ static void editing_panel_font_type(Object *ob, Curve *cu)
packdummy = 0;
}
uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE, 772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
uiDefBut(block, LABEL, 0, vfd->name, 480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
/* This doesn't work anyway */
// uiDefBut(block, LABEL, 0, vfd->name, 480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor");
uiBlockBeginAlign(block);
uiDefButC(block, TOG|BIT|0,B_STYLETOSEL, "B", 752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
uiDefButC(block, TOG|BIT|1,B_STYLETOSEL, "i", 772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");
uiBlockEndAlign(block);
MEM_freeN(strp);
@ -974,17 +1095,31 @@ static void editing_panel_font_type(Object *ob, Curve *cu)
uiDefBut(block, BUT, B_TOUPPER, "ToUpper", 715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
uiBlockEndAlign(block);
uiDefButS(block, TOG|BIT|9,B_FASTFONT, "Fast Edit", 715,105,78,20, &cu->flag, 0, 0, 0, 0, "Don't fill polygons while editing");
uiDefIDPoinBut(block, test_obpoin_but, B_TEXTONCURVE, "TextOnCurve:", 480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
uiBlockBeginAlign(block);
uiDefButF(block, NUM,B_MAKEFONT, "Size:", 480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
uiDefButF(block, NUM,B_MAKEFONT, "Linedist:", 640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:", 795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");
uiDefButF(block, NUM,B_MAKEFONT, "Spacing:", 480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
uiDefButF(block, NUM,B_MAKEFONT, "X offset:", 640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object centre");
uiDefButF(block, NUM,B_MAKEFONT, "Shear:", 480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
uiDefButF(block, NUM,B_MAKEFONT, "Y offset:", 640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object centre");
uiBlockEndAlign(block);
sprintf(str, "%d TextFrame: ", cu->totbox);
uiBlockBeginAlign(block);
uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");
uiDefButF(block, NUM,B_MAKEFONT, "X:", 805, 148, 72, 20, &(cu->tb[cu->actbox-1].x), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");
uiDefButF(block, NUM,B_MAKEFONT, "Y:", 877, 148, 73, 20, &(cu->tb[cu->actbox-1].y), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");
uiDefButF(block, NUM,B_MAKEFONT, "Width:", 805, 128, 145, 20, &(cu->tb[cu->actbox-1].w), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");
uiDefButF(block, NUM,B_MAKEFONT, "Height:", 805, 108, 145, 20, &(cu->tb[cu->actbox-1].h), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");
uiBlockEndAlign(block);
}
@ -2299,7 +2434,7 @@ static void editing_panel_links(Object *ob)
else poin= &( ((Curve *)ob->data)->texflag );
uiDefButI(block, TOG|BIT|0, B_AUTOTEX, "AutoTexSpace", 143,15,140,19, poin, 0, 0, 0, 0, "Adjusts active object's texture space automatically when transforming object");
sprintf(str,"%d Mat:", ob->totcol);
sprintf(str,"%d Mat ", ob->totcol);
if(ob->totcol) min= 1.0; else min= 0.0;
ma= give_current_material(ob, ob->actcol);

@ -76,6 +76,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_lattice.h"
@ -3408,6 +3409,11 @@ void draw_object(Base *base)
static int warning_recursive= 0;
int sel, drawtype, colindex= 0, ipoflag;
short dt, dtx, zbufoff= 0;
Material *ma;
float vec1[3], vec2[3];
int i, selstart, selend;
SelBox *sb;
float selboxw;
ob= base->object;
@ -3592,8 +3598,79 @@ void draw_object(Base *base)
cu= ob->data;
if(ob==G.obedit) {
tekentextcurs();
cpack(0xFFFF90);
drawDispList(ob, OB_WIRE);
if (cu->flag & CU_FAST) {
cpack(0xFFFFFF);
set_inverted_drawing(1);
drawDispList(ob, OB_WIRE);
set_inverted_drawing(0);
}
if (cu->linewidth != 0.0) {
BIF_ThemeColor(TH_WIRE);
VECCOPY(vec1, ob->orig);
VECCOPY(vec2, ob->orig);
vec1[0] += cu->linewidth;
vec2[0] += cu->linewidth;
vec1[1] += cu->linedist * cu->fsize;
vec2[1] -= cu->lines * cu->linedist * cu->fsize;
setlinestyle(3);
glBegin(GL_LINE_STRIP);
glVertex2fv(vec1);
glVertex2fv(vec2);
glEnd();
setlinestyle(0);
}
setlinestyle(3);
for (i=0; i<cu->totbox; i++) {
if (cu->tb[i].w != 0.0) {
if (i == (cu->actbox-1))
BIF_ThemeColor(TH_ACTIVE);
else
BIF_ThemeColor(TH_WIRE);
VECCOPY(vec1, ob->orig);
vec1[0] += cu->tb[i].x;
vec1[1] += cu->tb[i].y + cu->linedist*cu->fsize;
glBegin(GL_LINE_STRIP);
glVertex2fv(vec1);
vec1[0] += cu->tb[i].w;
glVertex2fv(vec1);
vec1[1] -= (cu->tb[i].h + cu->linedist*cu->fsize);
glVertex2fv(vec1);
vec1[0] -= cu->tb[i].w;
glVertex2fv(vec1);
vec1[1] += cu->tb[i].h + cu->linedist*cu->fsize;
glVertex2fv(vec1);
glEnd();
}
}
setlinestyle(0);
if (getselection(&selstart, &selend) && selboxes) {
cpack(0xffffff);
set_inverted_drawing(1);
for (i=0; i<(selend-selstart+1); i++) {
sb = &(selboxes[i]);
if (i<(selend-selstart)) {
if (selboxes[i+1].y == sb->y)
selboxw= selboxes[i+1].x - sb->x;
else
selboxw= sb->w;
}
else {
selboxw= sb->w;
}
glBegin(GL_QUADS);
glVertex3f(sb->x, sb->y, 0.001);
glVertex3f(sb->x+selboxw, sb->y, 0.001);
glVertex3f(sb->x+selboxw, sb->y+sb->h, 0.001);
glVertex3f(sb->x, sb->y+sb->h, 0.001);
glEnd();
}
set_inverted_drawing(0);
}
}
else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt);

@ -30,6 +30,7 @@
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
@ -76,13 +77,15 @@
#include "blendef.h"
#define MAXTEXT 1000
#define MAXTEXT 50000
/* -- prototypes --------*/
VFont *get_builtin_font(void);
int textediting=0;
extern struct SelBox *selboxes; /* from blenkernel/font.c */
static char findaccent(char char1, char code)
{
char new= 0;
@ -214,9 +217,13 @@ static char findaccent(char char1, char code)
else return char1;
}
static char *copybuf=NULL;
static char *copybufinfo=NULL;
static char *textbuf=NULL;
static CharInfo *textbufinfo=NULL;
static char *oldstr=NULL;
static CharInfo *oldstrinfo=NULL;
static int insert_into_textbuf(Curve *cu, char c)
{
@ -224,7 +231,14 @@ static int insert_into_textbuf(Curve *cu, char c)
int x;
for(x= cu->len; x>cu->pos; x--) textbuf[x]= textbuf[x-1];
for(x= cu->len; x>cu->pos; x--) textbufinfo[x]= textbufinfo[x-1];
textbuf[cu->pos]= c;
textbufinfo[cu->pos] = cu->curinfo;
textbufinfo[cu->pos].kern = 0;
if (G.obedit->actcol>0)
textbufinfo[cu->pos].mat_nr = G.obedit->actcol;
else
textbufinfo[cu->pos].mat_nr = 0;
cu->pos++;
cu->len++;
@ -236,6 +250,52 @@ static int insert_into_textbuf(Curve *cu, char c)
}
}
void add_lorem(void)
{
char *p, *p2;
int i;
Curve *cu=G.obedit->data;
static char* lastlorem;
if (lastlorem)
p= lastlorem;
else
p= BIF_lorem;
i= rand()/(RAND_MAX/6)+4;
for (p2=p; *p2 && i; p2++) {
insert_into_textbuf(cu, *p2);
if (*p2=='.') i--;
}
lastlorem = p2+1;
if (strlen(lastlorem)<5) lastlorem = BIF_lorem;
insert_into_textbuf(cu, '\n');
insert_into_textbuf(cu, '\n');
text_to_curve(G.obedit, 0);
text_makedisplist(G.obedit);
allqueue(REDRAWVIEW3D, 0);
}
void load_3dtext_fs(char *file)
{
FILE *fp;
int c;
fp= fopen(file, "r");
if (!fp) return;
while (!feof(fp)) {
c = fgetc(fp);
if (c!=EOF) insert_into_textbuf(OBACT->data, c);
}
fclose(fp);
text_to_curve(G.obedit, 0);
text_makedisplist(G.obedit);
allqueue(REDRAWVIEW3D, 0);
}
VFont *get_builtin_font(void)
{
@ -294,8 +354,10 @@ void txt_export_to_object(struct Text *text)
}
if(cu->str) MEM_freeN(cu->str);
if(cu->strinfo) MEM_freeN(cu->strinfo);
cu->str= MEM_mallocN(nchars+4, "str");
cu->strinfo= MEM_callocN((nchars+4)*sizeof(CharInfo), "strinfo");
tmp= text->lines.first;
strcpy(cu->str, tmp->line);
@ -371,8 +433,10 @@ void txt_export_to_objects(struct Text *text)
nchars = strlen(curline->line) + 1;
if(cu->str) MEM_freeN(cu->str);
if(cu->strinfo) MEM_freeN(cu->strinfo);
cu->str= MEM_mallocN(nchars+4, "str");
cu->strinfo= MEM_callocN((nchars+4)*sizeof(CharInfo), "strinfo");
strcpy(cu->str, curline->line);
cu->len= strlen(curline->line);
@ -389,7 +453,7 @@ void txt_export_to_objects(struct Text *text)
}
static void text_makedisplist(Object *ob)
void text_makedisplist(Object *ob)
{
Base *base;
// free displists of other users...
@ -399,12 +463,123 @@ static void text_makedisplist(Object *ob)
makeDispList(ob);
}
static short next_word(Curve *cu)
{
short s;
for (s=cu->pos; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
(cu->str[s]!=1) && (cu->str[s]!='\r'); s++);
if (cu->str[s]) return(s+1); else return(s);
}
static short prev_word(Curve *cu)
{
short s;
if (cu->pos==0) return(0);
for (s=cu->pos-2; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
(cu->str[s]!=1) && (cu->str[s]!='\r'); s--);
if (cu->str[s]) return(s+1); else return(s);
}
static int killselection(int ins) /* 1 == new character */
{
int selend, selstart, direction;
Curve *cu= G.obedit->data;
int offset = 0;
int getfrom;
direction = getselection(&selstart, &selend);
if (direction) {
if (ins) offset = 1;
if (cu->pos >= selstart) cu->pos = selstart+offset;
if ((direction == -1) && ins) {
selstart++;
selend++;
}
getfrom = selend+offset;
if (ins==0) getfrom++;
memmove(textbuf+selstart, textbuf+getfrom, (cu->len-selstart)+offset);
memmove(textbufinfo+selstart, textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
cu->len -= (selend-selstart)+offset;
cu->selstart = cu->selend = 0;
}
return(direction);
}
static void copyselection(void)
{
int selstart, selend;
if (getselection(&selstart, &selend)) {
memcpy(copybuf, textbuf+selstart, (selend-selstart)+1);
copybuf[(selend-selstart)+1]=0;
memcpy(copybufinfo, textbufinfo+selstart, ((selend-selstart)+1)*sizeof(CharInfo));
}
}
static void pasteselection(void)
{
Curve *cu= G.obedit->data;
int len= strlen(copybuf);
if (len) {
memmove(textbuf+cu->pos+len, textbuf+cu->pos, cu->len-cu->pos+1);
memcpy(textbuf+cu->pos, copybuf, len);
memmove(textbufinfo+cu->pos+len, textbufinfo+cu->pos, (cu->len-cu->pos+1)*sizeof(CharInfo));
memcpy(textbufinfo+cu->pos, copybufinfo, len*sizeof(CharInfo));
cu->len += len;
cu->pos += len;
}
}
int style_to_sel(void) {
int selstart, selend;
int i;
Curve *cu;
if (G.obedit && (G.obedit->type == OB_FONT)) {
cu= G.obedit->data;
if (getselection(&selstart, &selend)) {
for (i=selstart; i<=selend; i++) {
textbufinfo[i].flag &= ~CU_STYLE;
textbufinfo[i].flag |= (cu->curinfo.flag & CU_STYLE);
}
return 1;
}
}
return 0;
}
int mat_to_sel(void) {
int selstart, selend;
int i;
Curve *cu;
if (G.obedit && (G.obedit->type == OB_FONT)) {
cu= G.obedit->data;
if (getselection(&selstart, &selend)) {
for (i=selstart; i<=selend; i++) {
textbufinfo[i].mat_nr = G.obedit->actcol;
}
return 1;
}
}
return 0;
}
void do_textedit(unsigned short event, short val, char _ascii)
{
Curve *cu;
static int accentcode= 0;
int x, doit=0, cursmove=0;
int ascii = _ascii;
short kern;
cu= G.obedit->data;
@ -474,6 +649,8 @@ void do_textedit(unsigned short event, short val, char _ascii)
}
}
killselection(1);
doit= 1;
}
}
@ -481,45 +658,81 @@ void do_textedit(unsigned short event, short val, char _ascii)
cursmove= 0;
switch(event) {
case RETKEY:
insert_into_textbuf(cu, '\n');
doit= 1;
break;
case RIGHTARROWKEY:
if(G.qual & LR_SHIFTKEY) {
while(cu->pos<cu->len) {
if( textbuf[cu->pos]==0) break;
if( textbuf[cu->pos]=='\n') break;
cu->pos++;
}
}
else {
case ENDKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
while(cu->pos<cu->len) {
if( textbuf[cu->pos]==0) break;
if( textbuf[cu->pos]=='\n') break;
if( textbufinfo[cu->pos].flag & CU_WRAP ) break;
cu->pos++;
}
cursmove= FO_CURS;
cursmove=FO_CURS;
break;
case LEFTARROWKEY:
if(G.qual & LR_SHIFTKEY) {
while(cu->pos>0) {
if( textbuf[cu->pos-1]=='\n') break;
cu->pos--;
}
}
else {
case HOMEKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
while(cu->pos>0) {
if( textbuf[cu->pos-1]=='\n') break;
if( textbufinfo[cu->pos-1].flag & CU_WRAP ) break;
cu->pos--;
}
cursmove=FO_CURS;
break;
case UPARROWKEY:
if(G.qual & LR_SHIFTKEY) {
cu->pos= 0;
case RETKEY:
if(G.qual & LR_CTRLKEY) {
insert_into_textbuf(cu, 1);
if (textbuf[cu->pos]!='\n') insert_into_textbuf(cu, '\n');
}
else {
insert_into_textbuf(cu, '\n');
}
cu->selstart = cu->selend = 0;
doit= 1;
break;
case RIGHTARROWKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
if (G.qual & LR_CTRLKEY) {
cu->pos= next_word(cu);
cursmove= FO_CURS;
}
else if(G.qual & LR_ALTKEY) {
else if (G.qual & LR_ALTKEY) {
kern = textbufinfo[cu->pos-1].kern;
kern += 1;
if (kern>10) kern = 10;
textbufinfo[cu->pos-1].kern = kern;
doit = 1;
}
else {
cu->pos++;
cursmove= FO_CURS;
}
break;
case LEFTARROWKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
if (G.qual & LR_CTRLKEY) {
cu->pos= prev_word(cu);
cursmove= FO_CURS;
}
else if (G.qual & LR_ALTKEY) {
kern = textbufinfo[cu->pos-1].kern;
kern -= 1;
if (kern<-10) kern = -10;
textbufinfo[cu->pos-1].kern = kern;
doit = 1;
}
else {
cu->pos--;
cursmove=FO_CURS;
}
break;
case UPARROWKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
if(G.qual & LR_ALTKEY) {
if (cu->pos && textbuf[cu->pos - 1] < 255) {
textbuf[cu->pos - 1]++;
doit= 1;
@ -528,12 +741,14 @@ void do_textedit(unsigned short event, short val, char _ascii)
else cursmove=FO_CURSUP;
break;
case PAGEUPKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
cursmove=FO_PAGEUP;
break;
case DOWNARROWKEY:
if(G.qual & LR_SHIFTKEY) {
cu->pos= cu->len;
cursmove= FO_CURS;
}
else if(G.qual & LR_ALTKEY) {
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
if(G.qual & LR_ALTKEY) {
if (cu->pos && textbuf[cu->pos - 1] > 1) {
textbuf[cu->pos - 1]--;
doit= 1;
@ -542,44 +757,106 @@ void do_textedit(unsigned short event, short val, char _ascii)
else cursmove= FO_CURSDOWN;
break;
case PAGEDOWNKEY:
if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
cursmove=FO_PAGEDOWN;
break;
case BACKSPACEKEY:
if(cu->len!=0) {
if(G.qual & LR_ALTKEY) {
if(cu->pos>0) accentcode= 1;
}
else if(G.qual & LR_SHIFTKEY) {
cu->pos= 0;
textbuf[0]= 0;
cu->len= 0;
}
else if(cu->pos>0) {
for(x=cu->pos;x<=cu->len;x++) textbuf[x-1]= textbuf[x];
cu->pos--;
textbuf[--cu->len]='\0';
else {
if (killselection(0)==0) {
if (cu->pos>0) {
for(x=cu->pos;x<=cu->len;x++) textbuf[x-1]= textbuf[x];
for(x=cu->pos;x<=cu->len;x++) textbufinfo[x-1]= textbufinfo[x];
cu->pos--;
textbuf[--cu->len]='\0';
doit=1;
}
} else doit=1;
}
}
doit= 1;
break;
case DELKEY:
if(cu->len!=0) {
if(cu->pos<cu->len) {
for(x=cu->pos;x<cu->len;x++) textbuf[x]= textbuf[x+1];
textbuf[--cu->len]='\0';
}
if (killselection(0)==0) {
if(cu->pos<cu->len) {
for(x=cu->pos;x<cu->len;x++) textbuf[x]= textbuf[x+1];
for(x=cu->pos;x<cu->len;x++) textbufinfo[x]= textbufinfo[x+1];
textbuf[--cu->len]='\0';
doit=1;
}
} else doit=1;
}
doit= 1;
break;
}
case IKEY:
if (G.qual & LR_CTRLKEY) {
cu->curinfo.flag ^= CU_ITALIC;
if (style_to_sel()) doit= 1;
allqueue(REDRAWBUTSEDIT, 0);
}
break;
case BKEY:
if (G.qual & LR_CTRLKEY) {
cu->curinfo.flag ^= CU_BOLD;
if (style_to_sel()) doit= 1;
allqueue(REDRAWBUTSEDIT, 0);
}
break;
case XKEY:
if (G.qual & LR_CTRLKEY) {
copyselection();
killselection(0);
doit= 1;
}
break;
case CKEY:
if (G.qual & LR_CTRLKEY) {
copyselection();
}
break;
case VKEY:
if (G.qual & LR_CTRLKEY) {
pasteselection();
doit= 1;
}
break;
}
if(cursmove) {
if ((G.qual & LR_SHIFTKEY)==0) {
if (cu->selstart) {
cu->selstart = cu->selend = 0;
text_to_curve(G.obedit, FO_SELCHANGE);
allqueue(REDRAWVIEW3D, 0);
}
}
if(cu->pos>cu->len) cu->pos= cu->len;
else if(cu->pos>=MAXTEXT) cu->pos= MAXTEXT;
else if(cu->pos<0) cu->pos= 0;
}
}
if(doit || cursmove) {
if (cu->pos) cu->curinfo = textbufinfo[cu->pos-1];
if (G.obedit->totcol>0) {
G.obedit->actcol = textbufinfo[cu->pos-1].mat_nr;
}
allqueue(REDRAWBUTSEDIT, 0);
text_to_curve(G.obedit, cursmove);
if (cursmove && (G.qual & LR_SHIFTKEY)) {
cu->selend = cu->pos;
text_to_curve(G.obedit, FO_SELCHANGE);
}
if(cursmove==0) {
text_makedisplist(G.obedit);
}
@ -648,11 +925,18 @@ void make_editText(void)
cu= G.obedit->data;
if(textbuf==NULL) textbuf= MEM_mallocN(MAXTEXT+4, "texteditbuf");
if(textbufinfo==NULL) textbufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditbufinfo");
if(copybuf==NULL) copybuf= MEM_callocN(MAXTEXT+4, "texteditcopybuf");
if(copybufinfo==NULL) copybufinfo= MEM_callocN((MAXTEXT+4)*sizeof(CharInfo), "texteditcopybufinfo");
BLI_strncpy(textbuf, cu->str, MAXTEXT);
oldstr= cu->str;
cu->str= textbuf;
cu->len= strlen(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;
text_to_curve(G.obedit, 0);
@ -671,15 +955,32 @@ void load_editText(void)
MEM_freeN(oldstr);
oldstr= NULL;
MEM_freeN(oldstrinfo);
oldstrinfo= NULL;
cu->str= MEM_mallocN(cu->len+4, "textedit");
strcpy(cu->str, textbuf);
cu->strinfo= MEM_callocN((cu->len+4)*sizeof(CharInfo), "texteditinfo");
memcpy(cu->strinfo, textbufinfo, (cu->len)*sizeof(CharInfo));
cu->len= strlen(cu->str);
/* this memory system is weak... */
MEM_freeN(textbuf);
MEM_freeN(textbufinfo);
textbuf= NULL;
textbufinfo= NULL;
if (selboxes) {
MEM_freeN(selboxes);
selboxes= NULL;
}
MEM_freeN(copybuf);
MEM_freeN(copybufinfo);
copybuf= NULL;
copybufinfo= NULL;
cu->len= strlen(cu->str);
textediting= 0;
text_makedisplist(G.obedit);
@ -709,7 +1010,8 @@ void remake_editText(void)
void free_editText(void)
{
if(oldstr) MEM_freeN(oldstr);
textbuf= oldstr= NULL;
if(oldstrinfo) MEM_freeN(oldstrinfo);
textbuf= textbufinfo= oldstr= oldstrinfo= NULL;
textediting= 0;
}
@ -723,18 +1025,22 @@ void add_primitiveFont(int dummy_argument)
add_object_draw(OB_FONT);
base_init_from_view3d(BASACT, G.vd);
G.obedit= BASACT->object;
where_is_object(G.obedit);
cu= G.obedit->data;
where_is_object(BASACT->object);
cu->vfont= get_builtin_font();
cu->vfont->id.us++;
cu= BASACT->object->data;
cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font();
cu->vfont->id.us+=4;
cu->str= MEM_mallocN(12, "str");
strcpy(cu->str, "Text");
cu->pos= 4;
cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo");
cu->totbox= cu->actbox= 1;
cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
cu->tb[0].w = cu->tb[0].h = 0.0;
make_editText();
enter_editmode();
allqueue(REDRAWALL, 0);
}
@ -792,6 +1098,8 @@ static void undoFont_to_editFont(void *strv)
strncpy(textbuf, str+2, MAXTEXT);
cu->pos= *((short *)str);
cu->len= strlen(textbuf);
memcpy(textbufinfo, str+2+cu->len+1, cu->len*sizeof(CharInfo));
cu->selstart = cu->selend = 0;
text_to_curve(G.obedit, 0);
text_makedisplist(G.obedit);
@ -803,10 +1111,11 @@ static void *editFont_to_undoFont(void)
Curve *cu= G.obedit->data;
char *str;
str= MEM_callocN(MAXTEXT+4, "string undo");
str= MEM_callocN(MAXTEXT+4+(MAXTEXT+4)*sizeof(CharInfo), "string undo");
strncpy(str+2, textbuf, MAXTEXT);
*((short *)str)= cu->pos;
memcpy(str+2+cu->len+1, textbufinfo, cu->len*sizeof(CharInfo));
return str;
}

@ -173,6 +173,8 @@
/* --------------------------------- */
Base *dupfontbase;
void add_object_draw(int type) /* for toolbox or menus, only non-editmode stuff */
{
Object *ob;
@ -1363,6 +1365,7 @@ void enter_editmode(void)
Mesh *me;
int ok= 0;
bArmature *arm;
Curve *cu;
if(G.scene->id.lib) return;
base= BASACT;
@ -1418,6 +1421,20 @@ void enter_editmode(void)
allqueue(REDRAWVIEW3D, 0);
}
else if(ob->type==OB_FONT) {
cu= ob->data;
if ((cu->flag & CU_FAST)==0) {
base->flag |= SELECT;
ob->flag |= SELECT;
G.qual |= LR_ALTKEY; /* patch to make sure we get a linked duplicate */
adduplicate(1);
G.qual &= ~LR_ALTKEY;
dupfontbase = BASACT;
BASACT->flag &= ~SELECT;
BASACT->object->flag &= ~SELECT;
set_active_base(base);
base->flag |= SELECT;
base->object->flag |= SELECT;
}
G.obedit= ob;
ok= 1;
make_editText();
@ -1463,7 +1480,7 @@ void make_displists_by_parent(Object *ob) {
void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
{
Base *base;
Base *base, *oldbase;
Object *ob;
Curve *cu;
@ -1553,6 +1570,22 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
make_displists_by_parent(ob);
}
if ((ob->type == OB_FONT) && (freedata)) {
cu= ob->data;
if ((cu->flag & CU_FAST)==0) {
oldbase = BASACT;
BASACT->flag &= ~SELECT;
BASACT->object->flag &= ~SELECT;
set_active_base(dupfontbase);
BASACT->flag |= SELECT;
BASACT->object->flag |= SELECT;
delete_obj(1);
oldbase->flag |= SELECT;
oldbase->object->flag |= SELECT;
set_active_base(oldbase);
}
}
if(freedata) {
setcursor_space(SPACE_VIEW3D, CURSOR_STD);
@ -1890,6 +1923,31 @@ void movetolayer(void)
BIF_undo_push("Move to layer");
}
void split_font()
{
Object *ob = OBACT;
Base *oldbase = BASACT;
Curve *cu= ob->data;
char *p= cu->str;
int slen= strlen(p);
int i;
for (i = 0; i<=slen; p++, i++) {
adduplicate(1);
cu= OBACT->data;
cu->sepchar = i+1;
text_to_curve(OBACT, 0); // pass 1: only one letter, adapt position
text_to_curve(OBACT, 0); // pass 2: remake
freedisplist(&OBACT->disp);
makeDispList(OBACT);
OBACT->flag &= ~SELECT;
BASACT->flag &= ~SELECT;
oldbase->flag |= SELECT;
oldbase->object->flag |= SELECT;
set_active_base(oldbase);
}
}
void special_editmenu(void)
{
@ -2007,6 +2065,14 @@ void special_editmenu(void)
allqueue(REDRAWVIEW3D, 0);
}
else if (OBACT->type == OB_FONT) {
nr= pupmenu("Split %t|Characters%x1");
if (nr > 0) {
switch(nr) {
case 1: split_font();
}
}
}
}
}
else if(G.obedit->type==OB_MESH) {

@ -133,6 +133,8 @@ static void drawscredge_area(ScrArea *sa);
/**********************************************************************/
extern int textediting;
static void screen_set_cursor(bScreen *sc)
{
if (sc->winakt>3) {
@ -1286,7 +1288,7 @@ void screenmain(void)
}
}
else if(ELEM(event, LEFTARROWKEY, RIGHTARROWKEY)) {
if(val && (G.qual & LR_CTRLKEY)) {
if(textediting==0 && val && (G.qual & LR_CTRLKEY)) {
bScreen *sc= (event==LEFTARROWKEY)?G.curscreen->id.prev:G.curscreen->id.next;
if(is_allowed_to_change_screen(sc)) setscreen(sc);
g_activearea= NULL;

@ -52,7 +52,7 @@
#define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode))
static void set_inverted_drawing(int enable)
void set_inverted_drawing(int enable)
{
glLogicOp(enable?GL_INVERT:GL_COPY);

@ -983,7 +983,7 @@ int blenderqread(unsigned short event, short val)
break;
case XKEY:
if(textspace==0) {
if(textspace==0 && textediting==0) {
if(G.qual==LR_CTRLKEY) {
if(okee("Erase all")) {
strcpy(G.sce, BLI_gethome());