Better font metrics support.

This commit is contained in:
Kris Maglione 2009-10-30 03:06:14 -04:00
parent 6659d28663
commit e31731e8bc
8 changed files with 85 additions and 26 deletions

View File

@ -293,6 +293,8 @@ main(int argc, char *argv[]) {
loadcolor(&cnorm, readctl("normcolors "));
loadcolor(&csel, readctl("focuscolors "));
font = loadfont(readctl("font "));
sscanf(readctl("fontpad "), "%d %d %d %d", &font->pad.min.x, &font->pad.max.x,
&font->pad.min.x, &font->pad.max.y);
if(!font)
fatal("Can't load font %q", readctl("font "));

View File

@ -130,15 +130,15 @@ next:
static void
_menu_draw(bool draw) {
Rectangle r, rd, rp, r2;
Rectangle r, rd, rp, r2, extent;
CTuple *c;
Item *i;
int inputw, itemoff, end, pad, n;
int inputw, itemoff, end, pad, n, offset;
r = barwin->r;
r = rectsetorigin(r, ZP);
pad = (font->height & ~1);
pad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
rd = r;
rp = ZR; // SET(rp)
@ -208,7 +208,8 @@ _menu_draw(bool draw) {
r2.max.x = promptw + inputw;
drawstring(ibuf, font, r2, West, input.string, cnorm.fg);
r2.min.x = promptw + textwidth_l(font, input.string, input.pos - input.string) + pad/2 - 1;
extent = textextents_l(font, input.string, input.pos - input.string, &offset);
r2.min.x = promptw + offset + font->pad.min.x - extent.min.x + pad/2 - 1;
r2.max.x = r2.min.x + 2;
r2.min.y++;
r2.max.y--;
@ -236,7 +237,7 @@ menu_show(void) {
ltwidth = textwidth(font, "<");
pad = (font->height & ~1)/2;
height = font->height + 2;
height = labelh(font);
r = scr.rect;
if(ontop)

View File

@ -140,7 +140,7 @@ bar_draw(WMScreen *s) {
foreach_bar(s, b) {
b->r.min = ZP;
b->r.max.y = Dy(s->brect);
b->r.max.x = def.font->height & ~1;
b->r.max.x = (def.font->height & ~1) + def.font->pad.min.x + def.font->pad.max.x;
if(b->text && strlen(b->text))
b->r.max.x += textwidth(def.font, b->text);
width += Dx(b->r);

View File

@ -466,8 +466,8 @@ frame_draw(Frame *f) {
/* grabbox */
r.min = Pt(2, 2);
r.max.x = r.min.x + def.font->height - 3;
r.max.y -= 2;
r.max.x = r.min.x + Dy(r);
f->grabbox = r;
if(c->urgent)

View File

@ -35,6 +35,7 @@ enum {
LEXEC,
LFOCUSCOLORS,
LFONT,
LFONTPAD,
LGRABMOD,
LGROW,
LINCMODE,
@ -69,6 +70,7 @@ char *symtab[] = {
"exec",
"focuscolors",
"font",
"fontpad",
"grabmod",
"grow",
"incmode",
@ -265,6 +267,16 @@ getbase(const char **s, long *sign) {
return ret;
}
static bool
getint(const char *s, int *ret) {
long l;
bool res;
res = getlong(s, &l);
*ret = l;
return res;
}
bool
getlong(const char *s, long *ret) {
const char *end;
@ -537,6 +549,18 @@ message_root(void *p, IxpMsg *m) {
ret = "can't load font";
view_update(selview);
break;
case LFONTPAD:
if(!getint(msg_getword(m), &def.font->pad.min.x) ||
!getint(msg_getword(m), &def.font->pad.max.x) ||
!getint(msg_getword(m), &def.font->pad.max.y) ||
!getint(msg_getword(m), &def.font->pad.min.y))
ret = "invalid rectangle";
else {
for(n=0; n < nscreens; n++)
bar_resize(screens[n]);
view_update(selview);
}
break;
case LGRABMOD:
s = msg_getword(m);
if(!parsekey(s, &i, nil) || i == 0)
@ -598,6 +622,8 @@ readctl_root(void) {
}
bufprint("focuscolors %s\n", def.focuscolor.colstr);
bufprint("font %s\n", def.font->name);
bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
def.font->pad.max.y, def.font->pad.min.y);
bufprint("grabmod %s\n", def.grabmod);
bufprint("incmode %s\n", incmodetab[def.incmode]);
bufprint("normcolors %s\n", def.normcolor.colstr);

View File

@ -537,8 +537,9 @@ uint
drawstring(Image *dst, Font *font,
Rectangle r, Align align,
char *text, ulong col) {
Rectangle tr;
char *buf;
uint x, y, w, h, len;
uint x, y, width, height, len;
int shortened;
shortened = 0;
@ -547,14 +548,22 @@ drawstring(Image *dst, Font *font,
buf = emalloc(len+1);
memcpy(buf, text, len+1);
h = font->ascent + font->descent;
y = r.min.y + Dy(r) / 2 - h / 2 + font->ascent;
r.max.y -= font->pad.min.y;
r.min.y += font->pad.max.y;
height = font->ascent + font->descent;
y = r.min.y + Dy(r) / 2 - height / 2 + font->ascent;
width = Dx(r) - font->pad.min.x - font->pad.max.x - (font->height & ~1);
r.min.x += font->pad.min.x;
r.max.x -= font->pad.max.x;
/* shorten text if necessary */
w = 0;
tr = ZR;
while(len > 0) {
w = textwidth_l(font, buf, len + min(shortened, 3));
if(w <= Dx(r) - (font->height & ~1))
tr = textextents_l(font, buf, len + min(shortened, 3), nil);
if(Dx(tr) <= width)
break;
while(len > 0 && (buf[--len]&0xC0) == 0x80)
buf[len] = '.';
@ -562,7 +571,7 @@ drawstring(Image *dst, Font *font,
shortened++;
}
if(len == 0 || w > Dx(r))
if(len == 0 || Dx(tr) > width)
goto done;
/* mark shortened info in the string */
@ -571,13 +580,13 @@ drawstring(Image *dst, Font *font,
switch (align) {
case East:
x = r.max.x - (w + (font->height / 2));
x = r.max.x - (tr.max.x + (font->height / 2));
break;
case Center:
x = r.min.x + (Dx(r) - w) / 2;
x = r.min.x + (Dx(r) - Dx(tr)) / 2 - tr.min.x;
break;
default:
x = r.min.x + (font->height / 2);
x = r.min.x + (font->height / 2) - tr.min.x;
break;
}
@ -605,7 +614,7 @@ drawstring(Image *dst, Font *font,
done:
free(buf);
return w;
return Dx(tr);
}
void
@ -745,26 +754,44 @@ freefont(Font *f) {
free(f);
}
uint
textwidth_l(Font *font, char *text, uint len) {
Rectangle
textextents_l(Font *font, char *text, uint len, int *offset) {
Rectangle rect;
XRectangle r;
XGlyphInfo i;
int unused;
if(!offset)
offset = &unused;
switch(font->type) {
case FFontSet:
Xutf8TextExtents(font->font.set, text, len, nil, &r);
return r.width;
*offset = Xutf8TextExtents(font->font.set, text, len, &r, nil);
return Rect(r.x, -r.y - r.height, r.x + r.width, -r.y);
case FXft:
XftTextExtentsUtf8(display, font->font.xft, (uchar*)text, len, &i);
return i.width;
*offset = i.xOff;
return Rect(-i.x, i.y - i.height, -i.x + i.width, i.y);
case FX11:
return XTextWidth(font->font.x11, text, len);
rect = ZR;
rect.max.x = XTextWidth(font->font.x11, text, len);
rect.max.y = font->ascent;
*offset = rect.max.x;
return rect;
default:
die("Invalid font type");
return 0; /* shut up ken */
return ZR; /* shut up ken */
}
}
uint
textwidth_l(Font *font, char *text, uint len) {
Rectangle r;
r = textextents_l(font, text, len, nil);
return Dx(r);
}
uint
textwidth(Font *font, char *text) {
return textwidth_l(font, text, strlen(text));
@ -772,7 +799,7 @@ textwidth(Font *font, char *text) {
uint
labelh(Font *font) {
return font->height + 2;
return font->height + font->descent + font->pad.min.y + font->pad.max.y;
}
/* Misc */

View File

@ -367,6 +367,7 @@ struct exectab {
{0, }
}, utiltab[] = {
{"namespace", xnamespace},
{"ns", xnamespace},
{"setsid", xsetsid},
{0, }
};

View File

@ -91,6 +91,7 @@ struct Font {
XFontSet set;
XftFont* xft;
} font;
Rectangle pad;
int ascent;
int descent;
uint height;
@ -261,6 +262,7 @@ Point subpt(Point, Point);
void sync(void);
uint textwidth(Font*, char*);
uint textwidth_l(Font*, char*, uint len);
Rectangle textextents_l(Font*, char*, uint, int*);
int traperrors(bool);
Point translate(Window*, Window*, Point);
void ungrabkeyboard(void);