From 97df61a7e5391e302d1a5f9069cf0b388f85e0c8 Mon Sep 17 00:00:00 2001 From: Alexander Ewering Date: Fri, 17 Jun 2005 21:04:27 +0000 Subject: 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 === --- source/blender/blenkernel/BKE_displist.h | 2 + source/blender/blenkernel/BKE_font.h | 9 + source/blender/blenkernel/intern/curve.c | 8 + source/blender/blenkernel/intern/displist.c | 21 +- source/blender/blenkernel/intern/font.c | 305 ++++++++++++++----- source/blender/blenlib/intern/psfont.c | 14 +- source/blender/blenloader/intern/readfile.c | 20 ++ source/blender/blenloader/intern/writefile.c | 2 + source/blender/include/BIF_editfont.h | 5 + source/blender/include/BIF_glutil.h | 3 + source/blender/include/butspace.h | 8 +- source/blender/makesdna/DNA_curve_types.h | 47 ++- source/blender/makesdna/DNA_vfont_types.h | 3 + source/blender/src/buttons_editing.c | 157 +++++++++- source/blender/src/drawobject.c | 81 +++++- source/blender/src/editfont.c | 419 +++++++++++++++++++++++---- source/blender/src/editobject.c | 68 ++++- source/blender/src/editscreen.c | 4 +- source/blender/src/glutil.c | 2 +- source/blender/src/toets.c | 2 +- 20 files changed, 1016 insertions(+), 164 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 3193c8cbfec..ca08b5454a3 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -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); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 2f923315aaf..d99085f9ee9 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -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 diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 83c51de76d1..c118a109b8f 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -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; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 87aa3dc17b9..647ff535585 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -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(colnrcol) cont= 1; - else if(colnr==dl->col) { + if(charidxcharidx) 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) diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index fc1d45f9696..999b8315242 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -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; @@ -285,7 +314,7 @@ static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, fl } } bezt2 = nu2->bezt; - + for (i= nu2->pntsu; i > 0; i--) { fp= bezt2->vec[0]; @@ -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; + mem= cu->str; + slen = strlen(mem); - 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->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; istrinfo[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(istr[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; + + cu->lines= 1; + ct= chartransdata; + for (i= 0; i<=slen; i++, mem++, ct++) { + ascii = *mem; + if(ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++; + } - if(cu->spacemode==CU_RIGHT) { - for(i=0;ixof+= linedata[ct->linenr]; - ct++; - } - } else if(cu->spacemode==CU_MIDDLE) { - for(i=0;ixof+= linedata[ct->linenr]; - ct++; - } - } else if(cu->spacemode==CU_FLUSH) { - for(i=0;i1) - linedata[i]= ((maxlen-linedata[i])/(linedata2[i]-1)); - for (i=0; i<=slen; i++) { - ct->xof+= (ct->charnr*linedata[ct->linenr])-maxlen/2; - ct++; - } - } - } + // linedata is now: width of line + // linedata2 is now: number of characters + // linedata3 is now: maxlen of that line - /* old alignment here, to spot the differences */ -/* if(cu->spacemode!=CU_LEFT && lnr>1) { ct= chartransdata; if(cu->spacemode==CU_RIGHT) { - for(i=0;ixof+= linedata[ct->linenr]; ct++; } } else if(cu->spacemode==CU_MIDDLE) { - for(i=0;ixof+= 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;i1) - 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) && (jstr[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; istr[i]; - buildchar(cu, ascii, ct->xof, ct->yof, ct->rot); - ct++; + if (cu->sepchar==0) { + for (i= 0; istr[i]; + info = &(cu->strinfo[i]); + buildchar(cu, ascii, info, ct->xof, ct->yof, ct->rot, i); + ct++; + } } + else { + outta = 0; + for (i= 0; (istr[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; diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index 74e8bef6e8a..f7fbf7e3d16 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -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; itaperobj= 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); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 8ade6df7b4c..2b87df727ec 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -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 */ diff --git a/source/blender/include/BIF_editfont.h b/source/blender/include/BIF_editfont.h index fe3604493f5..5842edc898e 100644 --- a/source/blender/include/BIF_editfont.h +++ b/source/blender/include/BIF_editfont.h @@ -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 diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h index d776a9003f9..ba7e008d58a 100644 --- a/source/blender/include/BIF_glutil.h +++ b/source/blender/include/BIF_glutil.h @@ -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); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 7bbadba8847..8cc6ad4519d 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -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 diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 0713f770dc4..4482d24ba06 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -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; - - char *str, family[24]; + float linewidth; + + 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 diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h index 5f9e3f61446..df9279d6243 100644 --- a/source/blender/makesdna/DNA_vfont_types.h +++ b/source/blender/makesdna/DNA_vfont_types.h @@ -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 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 49fdf7fad67..0af92664773 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -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"); @@ -840,9 +847,25 @@ static void load_buts_vfont(char *name) if(vf==0) return; } 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); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index cb5f6d99384..058401c95a7 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -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; itotbox; 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); diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c index eb1032b9e7d..25297176e14 100644 --- a/source/blender/src/editfont.c +++ b/source/blender/src/editfont.c @@ -30,6 +30,7 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ +#include #include #include @@ -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 ENDKEY: + if ((G.qual & LR_SHIFTKEY) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1; + while(cu->poslen) { + 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; + break; + + 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 RETKEY: - insert_into_textbuf(cu, '\n'); + 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) { - while(cu->poslen) { - if( textbuf[cu->pos]==0) break; - if( textbuf[cu->pos]=='\n') break; - cu->pos++; - } - } + 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) { + 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; } - cursmove= FO_CURS; + break; case LEFTARROWKEY: - - if(G.qual & LR_SHIFTKEY) { - while(cu->pos>0) { - if( textbuf[cu->pos-1]=='\n') break; - cu->pos--; - } - } + 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; } - cursmove=FO_CURS; break; case UPARROWKEY: - if(G.qual & LR_SHIFTKEY) { - cu->pos= 0; - 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] < 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; @@ -541,45 +756,107 @@ 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->poslen) { - for(x=cu->pos;xlen;x++) textbuf[x]= textbuf[x+1]; - textbuf[--cu->len]='\0'; - } + if (killselection(0)==0) { + if(cu->poslen) { + for(x=cu->pos;xlen;x++) textbuf[x]= textbuf[x+1]; + for(x=cu->pos;xlen;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); + cu->len= strlen(textbuf); + + memcpy(textbufinfo, cu->strinfo, (cu->len)*sizeof(CharInfo)); oldstr= cu->str; + oldstrinfo= cu->strinfo; cu->str= textbuf; + cu->strinfo= textbufinfo; - cu->len= strlen(textbuf); 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; } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 8eb489a8ce5..edaaab474d3 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -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) { diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 20cada29b95..c11203343b1 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -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; diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index c1175806947..fcb32adc5b9 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -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); diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 552f846038f..5cc23d6914b 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -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()); -- cgit v1.2.3