diff options
author | Alexander Ewering <blender@instinctive.de> | 2005-08-29 16:46:07 +0400 |
---|---|---|
committer | Alexander Ewering <blender@instinctive.de> | 2005-08-29 16:46:07 +0400 |
commit | a07394ef2cfd8cb54e68e8bfb1e7210ee4b2b1b4 (patch) | |
tree | 2fcb1b06b7e8dd989510190b8242203c9175905a | |
parent | c921ee25cc71decc843b230fb28a7fb195fb6786 (diff) |
More text object fancyness, and fixes:
- "Flush" is now split into two seperate Alignment modes "Flush" and
"Justify":
- Justify does exactly the same as a normal word processor's justify
function does, and in addition, it uses *whitespace* instead of
*character spacing* (kerning) to fill lines. Much more readable.
- Flush is pretty much the old Blender "Flush" mode - and as such it
uses character spacing to fill lines. Just as Justify, this only
works with at least one textframe.
- Underlining for text objects. Not a lot to explain. New button "U" in
the editbuttons, and CTRL-U as hotkey toggle underlining for newly
entered characters or for the selection, just like CTRL-B/CTRL-I do for
bold/italic.
Underline height (thickness) and Underline position (vertical) can be
set in the editbuttons.
Implemented as CU_POLY polygon curves.
- The B, U and i buttons (and the corresponding CTRL-B/U/I keystrokes)
have been fixed to only affect *one* attribute at a time. Formerly,
hitting CTRL-B when no other style was active, on a text portion with
italics text, for example, would kill the italics and just apply bold.
Now, these attributes always add or substract only, but do not
replace the style.
- In the past, there were bugs with material indices uninitialized, and
thus crashes in the renderer with illegal material indices.
Even though I assume they have been fixed, I've put in a check that
checks (hah) if the material index of a character is illegal (bigger
than ob->totcol), and then sets it to zero, and spits out a warning
on stderr.
If you see such warnings, please report and link to the .blend.
- Bugfix: All alignment modes only worked if there were at least *two*
lines of text in the text object. Fixed
There's now a regression test file for text objects, please add to the
corresponding repository:
http://blender.instinctive.de/downloads/release/demo/text-regression.blend.gz
-rw-r--r-- | source/blender/blenkernel/BKE_font.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/displist.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/font.c | 143 | ||||
-rw-r--r-- | source/blender/include/butspace.h | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 6 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 31 | ||||
-rw-r--r-- | source/blender/src/editfont.c | 22 |
8 files changed, 169 insertions, 49 deletions
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 9367f4816b5..ab0fcf6b994 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -51,7 +51,7 @@ 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 style_to_sel(int style, int toggle); int mat_to_sel(void); void font_duplilist(struct Object *par); int getselection(int *start, int *end); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b1f8fcca6bf..9f26dc6d930 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -131,6 +131,7 @@ Curve *add_curve(int type) cu->wordspace = 1.0; cu->spacing= cu->linedist= 1.0; cu->fsize= 1.0; + cu->ulheight = 0.05; cu->texflag= CU_AUTOSPACE; cu->bb= unit_boundbox(); @@ -696,6 +697,9 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) /* allocate and initialize */ len= nu->pntsu*nu->pntsv; if(len==0) return; + + + sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1"); resolu= nu->resolu; @@ -827,6 +831,11 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) if (rowstride!=0) in = (float*) (((unsigned char*) in) + (rowstride - 3*nu->resolv*sizeof(*in))); } + for (i=0; i<144*3; i++) { +// fprintf(stderr, "%f %f %f\n", nu->bp[i].vec[0], nu->bp[i].vec[1], nu->bp[i].vec[2]); + fprintf(stderr, "%f ", data[i]); + } + /* free */ MEM_freeN(sum); MEM_freeN(basisu); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 96930e78408..077060b7890 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1138,6 +1138,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) dl->parts= 1; dl->nr= len; dl->col= nu->mat_nr; + dl->charidx = nu->charidx; data= dl->verts; if(nu->flagu & 1) dl->type= DL_POLY; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 40c62e2c407..1799f01dd30 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -151,11 +151,7 @@ static VFontData *vfont_get_data(VFont *vfont) } if (pf) { -#ifdef WITH_FREETYPE2 - vfont->data= BLI_vfontdata_from_freetypefont(pf); -#else vfont->data= BLI_vfontdata_from_psfont(pf); -#endif if (pf != vfont->packedfile) { freePackedFile(pf); } @@ -192,11 +188,7 @@ VFont *load_vfont(char *name) waitcursor(1); -#ifdef WITH_FREETYPE2 - vfd= BLI_vfontdata_from_freetypefont(pf); -#else vfd= BLI_vfontdata_from_psfont(pf); -#endif if (vfd) { vfont = alloc_libblock(&G.main->vfont, ID_VF, filename); @@ -233,6 +225,54 @@ static VFont *which_vfont(Curve *cu, CharInfo *info) } } +static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr) +{ + Nurb *nu2; + BPoint *bp; + + nu2 =(Nurb*) MEM_callocN(sizeof(Nurb),"underline_nurb"); + if (nu2 == NULL) return; + nu2->resolu= cu->resolu; + nu2->bezt = NULL; + nu2->knotsu = nu2->knotsv = 0; + nu2->flag= 0; + nu2->charidx = charidx+1000; + nu2->mat_nr= mat_nr; + nu2->pntsu = 4; + nu2->pntsv = 1; + nu2->orderu = 4; + nu2->orderv = 1; + nu2->flagu = CU_CYCLIC; + + bp = (BPoint*)MEM_callocN(4 * sizeof(BPoint),"underline_bp"); + if (bp == 0){ + MEM_freeN(nu2); + return; + } + nu2->bp = bp; + + nu2->bp[0].vec[0] = x1; + nu2->bp[0].vec[1] = y1; + nu2->bp[0].vec[2] = 0; + nu2->bp[0].vec[3] = 1.0; + nu2->bp[1].vec[0] = x2; + nu2->bp[1].vec[1] = y1; + nu2->bp[1].vec[2] = 0; + nu2->bp[1].vec[3] = 1.0; + nu2->bp[2].vec[0] = x2; + nu2->bp[2].vec[1] = y2; + nu2->bp[2].vec[2] = 0; + nu2->bp[2].vec[3] = 1.0; + nu2->bp[3].vec[0] = x1; + nu2->bp[3].vec[1] = y2; + nu2->bp[3].vec[2] = 0; + nu2->bp[3].vec[3] = 1.0; + + nu2->type = CU_2D; + BLI_addtail(&(cu->nurb), nu2); + +} + static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx, float ofsy, float rot, int charidx) { BezTriple *bezt1, *bezt2; @@ -272,7 +312,12 @@ static void buildchar(Curve *cu, unsigned char ascii, CharInfo *info, float ofsx nu2->knotsu = nu2->knotsv = 0; nu2->flag= CU_SMOOTH; nu2->charidx = charidx; - if (info->mat_nr) nu2->mat_nr= info->mat_nr-1; + if (info->mat_nr) { + nu2->mat_nr= info->mat_nr-1; + } + else { + nu2->mat_nr= 0; + } /* nu2->trim.first = 0; */ /* nu2->trim.last = 0; */ i = nu2->pntsu; @@ -363,14 +408,15 @@ struct chartrans *text_to_curve(Object *ob, int mode) 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, *linedata3; + float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4; int i, slen, oldflag, j; - short cnr=0, lnr=0; + short cnr=0, lnr=0, wsnr= 0; char ascii, *mem; int outta; - float vecyo[3]; + float vecyo[3], curofs; CharInfo *info; float wsfac; + float ulwidth, uloverlap; TextBox *tb; int curbox; int selstart, selend; @@ -383,9 +429,10 @@ struct chartrans *text_to_curve(Object *ob, int mode) cu= ob->data; mem= cu->str; - if (cu->str==0) return 0; slen = strlen(mem); + if (cu->ulheight == 0.0) cu->ulheight = 0.05; + if (cu->str==0) return 0; if (cu->strinfo==NULL) { /* old file */ cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat"); } @@ -399,6 +446,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) linedata= MEM_mallocN(sizeof(float)*(slen+2),"buildtext2"); linedata2= MEM_mallocN(sizeof(float)*(slen+2),"buildtext3"); linedata3= MEM_callocN(sizeof(float)*(slen+2),"buildtext4"); + linedata4= MEM_callocN(sizeof(float)*(slen+2),"buildtext5"); linedist= cu->linedist; @@ -432,9 +480,11 @@ struct chartrans *text_to_curve(Object *ob, int mode) 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]==' ') { + if (cu->str[j]==' ' || cu->str[j]=='-') { ct -= (i-(j-1)); cnr -= (i-(j-1)); + if (cu->str[j] == ' ') wsnr--; + if (cu->str[j] == '-') wsnr++; i = j-1; xof = ct->xof; ct[1].dobreak = 1; @@ -465,6 +515,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) linedata[lnr]= xof-tb->x/cu->fsize; linedata2[lnr]= cnr; linedata3[lnr]= tb->w/cu->fsize; + linedata4[lnr]= wsnr; if ( (tb->h != 0.0) && ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize))) && @@ -478,6 +529,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) xof= cu->xof + (tb->x/cu->fsize); lnr++; cnr= 0; + wsnr= 0; } else if(ascii==9) { /* TAB */ ct->xof= xof; @@ -502,7 +554,10 @@ struct chartrans *text_to_curve(Object *ob, int mode) sb->w = xof*cu->fsize; } - if (ascii==32) wsfac = cu->wordspace; else wsfac = 1.0; + if (ascii==32) { + wsfac = cu->wordspace; + wsnr++; + } else wsfac = 1.0; xof += (vfd->width[ascii]*wsfac*(1.0+(info->kern/40.0)) ) + xtrax; if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w; @@ -510,6 +565,8 @@ struct chartrans *text_to_curve(Object *ob, int mode) ct++; } + + cu->lines= 1; ct= chartransdata; for (i= 0; i<=slen; i++, mem++, ct++) { @@ -520,8 +577,9 @@ struct chartrans *text_to_curve(Object *ob, int mode) // linedata is now: width of line // linedata2 is now: number of characters // linedata3 is now: maxlen of that line + // linedata4 is now: number of whitespaces of line - if(cu->spacemode!=CU_LEFT && lnr>1) { + if(cu->spacemode!=CU_LEFT) { ct= chartransdata; if(cu->spacemode==CU_RIGHT) { @@ -536,7 +594,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) ct->xof+= linedata[ct->linenr]; ct++; } - } else if((cu->spacemode==CU_FLUSH || cu->spacemode==CU_FORCEFLUSH) && + } else if((cu->spacemode==CU_FLUSH) && (cu->tb[0].w != 0.0)) { for(i=0;i<lnr;i++) if(linedata2[i]>1) @@ -544,12 +602,25 @@ struct chartrans *text_to_curve(Object *ob, int mode) for (i=0; i<=slen; i++) { for (j=i; (cu->str[j]) && (cu->str[j]!='\n') && (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++); - if ((cu->str[j]!='\r') && (cu->str[j]!='\n') && - (cu->spacemode==CU_FORCEFLUSH || (chartransdata[j].dobreak!=0))) { +// if ((cu->str[j]!='\r') && (cu->str[j]!='\n') && (cu->str[j])) { ct->xof+= ct->charnr*linedata[ct->linenr]; - } +// } ct++; } + } else if((cu->spacemode==CU_JUSTIFY) && + (cu->tb[0].w != 0.0)) { + curofs= 0; + for (i=0; i<=slen; i++) { + for (j=i; (cu->str[j]) && (cu->str[j]!='\n') && + (cu->str[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++); + if ((cu->str[j]!='\r') && (cu->str[j]!='\n') && + ((chartransdata[j].dobreak!=0))) { + if (cu->str[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr]; + ct->xof+= curofs; + } + if (cu->str[i]=='\n' || cu->str[i]=='\r' || chartransdata[i].dobreak) curofs= 0; + ct++; + } } } @@ -593,7 +664,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) else if(cu->spacemode==CU_MIDDLE) { timeofs= (1.0f-distfac)/2.0f; } - else if(cu->spacemode==CU_FLUSH || cu->spacemode==CU_FORCEFLUSH) distfac= 1.0f; + else if(cu->spacemode==CU_FLUSH) distfac= 1.0f; } else distfac= 1.0; @@ -696,11 +767,13 @@ struct chartrans *text_to_curve(Object *ob, int mode) } + MEM_freeN(linedata); + MEM_freeN(linedata2); + MEM_freeN(linedata3); + MEM_freeN(linedata4); + if (mode == FO_SELCHANGE) { MEM_freeN(chartransdata); - MEM_freeN(linedata); - MEM_freeN(linedata2); - MEM_freeN(linedata3); return NULL; } @@ -714,7 +787,24 @@ struct chartrans *text_to_curve(Object *ob, int mode) for (i= 0; i<slen; i++) { ascii = cu->str[i]; info = &(cu->strinfo[i]); + if (info->mat_nr > (ob->totcol)) { + printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); + info->mat_nr = 0; + } buildchar(cu, ascii, info, ct->xof, ct->yof, ct->rot, i); + if ((info->flag & CU_UNDERLINE) && (ascii != '\n') && (ascii != '\r')) { + uloverlap = 0; + if ( (i<(slen-1)) && (cu->str[i+1] != '\n') && (cu->str[i+1] != '\r') && + ((cu->str[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0) + ) { + uloverlap = xtrax + 0.1; + } + ulwidth = cu->fsize * ((vfd->width[ascii]* (1.0+(info->kern/40.0)))+uloverlap); + build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize, + ct->xof*cu->fsize + ulwidth, + ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize, + i, info->mat_nr); + } ct++; } } @@ -742,10 +832,6 @@ struct chartrans *text_to_curve(Object *ob, int mode) } } - MEM_freeN(linedata); - MEM_freeN(linedata2); - MEM_freeN(linedata3); - if(mode==FO_DUPLI) { return chartransdata; } @@ -754,7 +840,6 @@ struct chartrans *text_to_curve(Object *ob, int mode) return 0; } - /* ***************** DUPLI ***************** */ static Object *find_family_object(Object **obar, char *family, char ch) diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index e06b3591802..78254a10f81 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -404,7 +404,9 @@ enum { #define B_FASTFONT 2209 #define B_INSTB 2210 #define B_DELTB 2211 -#define B_STYLETOSEL 2212 +#define B_STYLETOSELB 2212 +#define B_STYLETOSELU 2213 +#define B_STYLETOSELI 2214 /* *********************** */ #define B_ARMBUTS 2400 diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 460e5f92431..5c99671dd54 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -149,7 +149,7 @@ typedef struct Curve { /* font part */ short len, lines, pos, spacemode; - float spacing, linedist, shear, fsize, wordspace; + float spacing, linedist, shear, fsize, wordspace, ulpos, ulheight; float xof, yof; float linewidth; @@ -211,8 +211,8 @@ typedef struct IpoCurve { #define CU_LEFT 0 #define CU_MIDDLE 1 #define CU_RIGHT 2 -#define CU_FLUSH 3 -#define CU_FORCEFLUSH 4 +#define CU_JUSTIFY 3 +#define CU_FLUSH 4 /* flag (nurb) */ #define CU_SMOOTH 1 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 2b7cf7cae01..f43ba188bce 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1251,7 +1251,7 @@ void do_fontbuts(unsigned short event) Object *ob; ScrArea *sa; char str[80]; - int i; + int i, style; ob= OBACT; @@ -1261,13 +1261,21 @@ void do_fontbuts(unsigned short event) allqueue(REDRAWVIEW3D, 0); break; - case B_STYLETOSEL: - if (style_to_sel()) { - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + case B_STYLETOSELU: + case B_STYLETOSELB: + case B_STYLETOSELI: + switch (event) { + case B_STYLETOSELU: style = CU_UNDERLINE; break; + case B_STYLETOSELB: style = CU_BOLD; break; + case B_STYLETOSELI: style = CU_ITALIC; break; + } + if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) { + text_to_curve(ob, 0); + makeDispListCurveTypes(ob, 0); allqueue(REDRAWVIEW3D, 0); } allqueue(REDRAWBUTSEDIT, 0); - break; + break; case B_FASTFONT: if (G.obedit) { @@ -1447,9 +1455,10 @@ static void editing_panel_font_type(Object *ob, Curve *cu) 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"); + uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U", 727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSEL, "B", 752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, ""); - uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSEL, "i", 772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, ""); + uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B", 752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, ""); + uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i", 772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, ""); uiBlockEndAlign(block); MEM_freeN(strp); @@ -1458,8 +1467,8 @@ static void editing_panel_font_type(Object *ob, Curve *cu) uiDefButS(block, ROW,B_MAKEFONT, "Left", 480,135,47,20, &cu->spacemode, 0.0,0.0, 0, 0, "Left align the text from the object centre"); uiDefButS(block, ROW,B_MAKEFONT, "Center", 527,135,47,20, &cu->spacemode, 0.0,1.0, 0, 0, "Middle align the text from the object centre"); uiDefButS(block, ROW,B_MAKEFONT, "Right", 574,135,47,20, &cu->spacemode, 0.0,2.0, 0, 0, "Right align the text from the object centre"); - uiDefButS(block, ROW,B_MAKEFONT, "Justify", 621,135,47,20, &cu->spacemode, 0.0,3.0, 0, 0, "Fill completed lines to maximum textframe width"); - uiDefButS(block, ROW,B_MAKEFONT, "Flush", 668,135,47,20, &cu->spacemode, 0.0,4.0, 0, 0, "Always fill to maximum textframe width"); + uiDefButS(block, ROW,B_MAKEFONT, "Justify", 621,135,47,20, &cu->spacemode, 0.0,3.0, 0, 0, "Fill completed lines to maximum textframe width by expanding whitespace"); + uiDefButS(block, ROW,B_MAKEFONT, "Flush", 668,135,47,20, &cu->spacemode, 0.0,4.0, 0, 0, "Fill every line to maximum textframe width, distributing space among all characters"); 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); uiDefButBitS(block, TOG, CU_FAST, B_FASTFONT, "Fast Edit", 715,105,78,20, &cu->flag, 0, 0, 0, 0, "Don't fill polygons while editing"); @@ -1473,9 +1482,11 @@ static void editing_panel_font_type(Object *ob, Curve *cu) 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, "UL position:", 795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline"); 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); + uiDefButF(block, NUM,B_MAKEFONT, "UL height:", 795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline"); + uiBlockEndAlign(block); sprintf(str, "%d TextFrame: ", cu->totbox); uiBlockBeginAlign(block); diff --git a/source/blender/src/editfont.c b/source/blender/src/editfont.c index a1253007d3d..278c70eb15f 100644 --- a/source/blender/src/editfont.c +++ b/source/blender/src/editfont.c @@ -523,7 +523,8 @@ static void pasteselection(void) } } -int style_to_sel(void) { +int style_to_sel(int style, int toggle) +{ int selstart, selend; int i; Curve *cu; @@ -533,8 +534,11 @@ int style_to_sel(void) { if (getselection(&selstart, &selend)) { for (i=selstart; i<=selend; i++) { - textbufinfo[i].flag &= ~CU_STYLE; - textbufinfo[i].flag |= (cu->curinfo.flag & CU_STYLE); + if (toggle==0) { + textbufinfo[i].flag &= ~style; + } else { + textbufinfo[i].flag |= style; + } } return 1; } @@ -789,7 +793,7 @@ void do_textedit(unsigned short event, short val, char _ascii) case IKEY: if (G.qual & LR_CTRLKEY) { cu->curinfo.flag ^= CU_ITALIC; - if (style_to_sel()) doit= 1; + if (style_to_sel(CU_ITALIC, cu->curinfo.flag & CU_ITALIC)) doit= 1; allqueue(REDRAWBUTSEDIT, 0); } break; @@ -797,11 +801,19 @@ void do_textedit(unsigned short event, short val, char _ascii) case BKEY: if (G.qual & LR_CTRLKEY) { cu->curinfo.flag ^= CU_BOLD; - if (style_to_sel()) doit= 1; + if (style_to_sel(CU_BOLD, cu->curinfo.flag & CU_BOLD)) doit= 1; allqueue(REDRAWBUTSEDIT, 0); } break; + case UKEY: + if (G.qual & LR_CTRLKEY) { + cu->curinfo.flag ^= CU_UNDERLINE; + if (style_to_sel(CU_UNDERLINE, cu->curinfo.flag & CU_UNDERLINE)) doit= 1; + allqueue(REDRAWBUTSEDIT, 0); + } + break; + case XKEY: if (G.qual & LR_CTRLKEY) { copyselection(); |