Introduction
Introduction Statistics Contact Development Disclaimer Help
tAdding fallback support to st. - st - [fork] customized build of st, the simpl…
git clone git://src.adamsgaard.dk/st
Log
Files
Refs
README
LICENSE
---
commit 9c44229c626ea7351a7809540435f40cffb624bc
parent 082bab29f3551e5cee332832ff767c3fb65a5cbc
Author: Christoph Lohmann <[email protected]>
Date: Fri, 28 Dec 2012 23:52:04 +0100
Adding fallback support to st.
Diffstat:
M st.c | 201 +++++++++++++++++++++++++++++…
1 file changed, 188 insertions(+), 13 deletions(-)
---
diff --git a/st.c b/st.c
t@@ -275,7 +275,9 @@ typedef struct {
int descent;
short lbearing;
short rbearing;
- XftFont *set;
+ XftFont *match;
+ FcFontSet *set;
+ FcPattern *pattern;
} Font;
/* Drawing Context */
t@@ -338,10 +340,13 @@ static void xclear(int, int, int, int);
static void xdrawcursor(void);
static void xinit(void);
static void xloadcols(void);
+static int xloadfont(Font *, FcPattern *);
+static void xloadfonts(char *, int);
static void xresettitle(void);
static void xseturgency(int);
static void xsetsel(char*);
static void xtermclear(int, int, int, int);
+static void xunloadfonts(void);
static void xresize(int, int);
static void expose(XEvent *);
t@@ -350,7 +355,7 @@ static void unmap(XEvent *);
static char *kmap(KeySym, uint);
static void kpress(XEvent *);
static void cmessage(XEvent *);
-static void cresize(int width, int height);
+static void cresize(int, int);
static void resize(XEvent *);
static void focus(XEvent *);
static void brelease(XEvent *);
t@@ -373,7 +378,7 @@ static int isfullutf8(char *, int);
static ssize_t xwrite(int, char *, size_t);
static void *xmalloc(size_t);
static void *xrealloc(void *, size_t);
-static void *xcalloc(size_t nmemb, size_t size);
+static void *xcalloc(size_t, size_t);
static void (*handler[LASTEvent])(XEvent *) = {
[KeyPress] = kpress,
t@@ -412,6 +417,28 @@ static char *opt_font = NULL;
static char *usedfont = NULL;
static int usedfontsize = 0;
+/* Font Ring Cache */
+enum {
+ FRC_NORMAL,
+ FRC_ITALIC,
+ FRC_BOLD,
+ FRC_ITALICBOLD
+};
+
+typedef struct {
+ XftFont *font;
+ long c;
+ int flags;
+} Fontcache;
+
+/*
+ * Fontcache is a ring buffer, with frccur as current position and frclen as
+ * the current length of used elements.
+ */
+
+static Fontcache frc[256];
+static int frccur = 0, frclen = 0;
+
ssize_t
xwrite(int fd, char *s, size_t len) {
size_t aux = len;
t@@ -2282,20 +2309,28 @@ xloadfont(Font *f, FcPattern *pattern) {
FcPattern *match;
FcResult result;
- match = XftFontMatch(xw.dpy, xw.scr, pattern, &result);
+ match = FcFontMatch(NULL, pattern, &result);
if(!match)
return 1;
- if(!(f->set = XftFontOpenPattern(xw.dpy, match))) {
+
+ if(!(f->set = FcFontSort(0, match, FcTrue, 0, &result))) {
+ FcPatternDestroy(match);
+ return 1;
+ }
+
+ if(!(f->match = XftFontOpenPattern(xw.dpy, match))) {
FcPatternDestroy(match);
return 1;
}
- f->ascent = f->set->ascent;
- f->descent = f->set->descent;
+ f->pattern = FcPatternDuplicate(pattern);
+
+ f->ascent = f->match->ascent;
+ f->descent = f->match->descent;
f->lbearing = 0;
- f->rbearing = f->set->max_advance_width;
+ f->rbearing = f->match->max_advance_width;
- f->height = f->set->height;
+ f->height = f->match->height;
f->width = f->lbearing + f->rbearing;
return 0;
t@@ -2334,6 +2369,9 @@ xloadfonts(char *fontstr, int fontsize) {
}
}
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
if(xloadfont(&dc.font, pattern))
die("st: can't open font %s\n", fontstr);
t@@ -2359,8 +2397,40 @@ xloadfonts(char *fontstr, int fontsize) {
}
void
+xunloadfonts(void)
+{
+ int i, ip;
+
+ /*
+ * Free the loaded fonts in the font cache. This is done backwards
+ * from the frccur.
+ */
+ for (i = 0, ip = frccur; i < frclen; i++, ip--) {
+ if (ip <= 0)
+ ip = LEN(frc) - 1;
+ XftFontClose(xw.dpy, frc[ip].font);
+ }
+ frccur = 0;
+ frclen = 0;
+
+ XftFontClose(xw.dpy, dc.font.match);
+ FcPatternDestroy(dc.font.pattern);
+ FcFontSetDestroy(dc.font.set);
+ XftFontClose(xw.dpy, dc.bfont.match);
+ FcPatternDestroy(dc.bfont.pattern);
+ FcFontSetDestroy(dc.bfont.set);
+ XftFontClose(xw.dpy, dc.ifont.match);
+ FcPatternDestroy(dc.ifont.pattern);
+ FcFontSetDestroy(dc.ifont.set);
+ XftFontClose(xw.dpy, dc.ibfont.match);
+ FcPatternDestroy(dc.ibfont.pattern);
+ FcFontSetDestroy(dc.ibfont.set);
+}
+
+void
xzoom(const Arg *arg)
{
+ xunloadfonts();
xloadfonts(usedfont, usedfontsize + arg->i);
cresize(0, 0);
draw();
t@@ -2379,6 +2449,9 @@ xinit(void) {
xw.vis = XDefaultVisual(xw.dpy, xw.scr);
/* font */
+ if (!FcInit())
+ die("Could not init fontconfig.\n");
+
usedfont = (opt_font == NULL)? font : opt_font;
xloadfonts(usedfont, 0);
t@@ -2459,13 +2532,22 @@ xinit(void) {
void
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
- width = charlen * xw.cw;
+ width = charlen * xw.cw, u8clen, xp, i, frp, frcflags;
+ long u8char;
+ char *u8c;
Font *font = &dc.font;
+ XftFont *sfont;
+ FcResult fcres;
+ FcPattern *fcpattern, *fontpattern;
+ FcFontSet *fcsets[] = { NULL };
+ FcCharSet *fccharset;
XGlyphInfo extents;
Colour *fg = &dc.col[base.fg], *bg = &dc.col[base.bg],
*temp, revfg, revbg;
XRenderColor colfg, colbg;
+ frcflags = FRC_NORMAL;
+
if(base.mode & ATTR_BOLD) {
if(BETWEEN(base.fg, 0, 7)) {
/* basic system colors */
t@@ -2484,12 +2566,17 @@ xdraws(char *s, Glyph base, int x, int y, int charlen,…
* 252 - 255 – brightest colors in greyscale
*/
font = &dc.bfont;
+ frcflags = FRC_BOLD;
}
- if(base.mode & ATTR_ITALIC)
+ if(base.mode & ATTR_ITALIC) {
font = &dc.ifont;
- if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD))
+ frcflags = FRC_ITALIC;
+ }
+ if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) {
font = &dc.ibfont;
+ frcflags = FRC_ITALICBOLD;
+ }
if(IS_SET(MODE_REVERSE)) {
if(fg == &dc.col[defaultfg]) {
t@@ -2521,7 +2608,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, i…
bg = temp;
}
- XftTextExtentsUtf8(xw.dpy, font->set, (FcChar8 *)s, bytelen,
+ /* Width of the whole string that should be printed. */
+ XftTextExtentsUtf8(xw.dpy, font->match, (FcChar8 *)s, bytelen,
&extents);
width = extents.xOff;
t@@ -2539,9 +2627,96 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, …
if(y == term.row-1)
xclear(winx, winy + xw.ch, winx + width, xw.h);
+ /* Clean up the region we want to draw to. */
XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch);
+
+ /*
+ * Step through all UTF-8 characters one by one and search in the font
+ * cache ring buffer, whether there was some font found to display the
+ * unicode value of that UTF-8 character.
+ */
+ fcsets[0] = font->set;
+ for (xp = winx; bytelen > 0; ) {
+ u8c = s;
+ u8clen = utf8decode(s, &u8char);
+ s += u8clen;
+ bytelen -= u8clen;
+
+ sfont = font->match;
+ /*
+ * Only check the font cache or load new fonts, if the
+ * characters is not represented in main font.
+ */
+ if (!XftCharExists(xw.dpy, font->match, u8char)) {
+ frp = frccur;
+ /* Search the font cache. */
+ for (i = 0; i < frclen; i++, frp--) {
+ if (frp <= 0)
+ frp = LEN(frc) - 1;
+
+ if (frc[frp].c == u8char
+ && frc[frp].flags == frcflags) {
+ break;
+ }
+ }
+ if (i >= frclen) {
+ /*
+ * Nothing was found in the cache. Now use
+ * some dozen of Fontconfig calls to get the
+ * font for one single character.
+ */
+ fcpattern = FcPatternDuplicate(font->pattern);
+ fccharset = FcCharSetCreate();
+
+ FcCharSetAddChar(fccharset, u8char);
+ FcPatternAddCharSet(fcpattern, FC_CHARSET,
+ fccharset);
+ FcPatternAddBool(fcpattern, FC_SCALABLE,
+ FcTrue);
+
+ FcConfigSubstitute(0, fcpattern,
+ FcMatchPattern);
+ FcDefaultSubstitute(fcpattern);
+
+ fontpattern = FcFontSetMatch(0, fcsets,
+ FcTrue, fcpattern, &fcres);
+
+ frccur++;
+ frclen++;
+ if (frccur >= LEN(frc))
+ frccur = 0;
+ if (frclen >= LEN(frc)) {
+ frclen = LEN(frc);
+ XftFontClose(xw.dpy, frc[frccur].font);
+ }
+
+ /*
+ * Overwrite or create the new cache entry
+ * entry.
+ */
+ frc[frccur].font = XftFontOpenPattern(xw.dpy,
+ fontpattern);
+ frc[frccur].c = u8char;
+ frc[frccur].flags = frcflags;
+
+ FcPatternDestroy(fcpattern);
+ FcCharSetDestroy(fccharset);
+
+ frp = frccur;
+ }
+ sfont = frc[frp].font;
+ }
+
+ XftDrawStringUtf8(xw.draw, fg, sfont, xp, winy + sfont->ascent,
+ (FcChar8 *)u8c, u8clen);
+
+ xp += font->width;
+ }
+
+ /*
XftDrawStringUtf8(xw.draw, fg, font->set, winx,
winy + font->ascent, (FcChar8 *)s, bytelen);
+ */
if(base.mode & ATTR_UNDERLINE) {
XftDrawRect(xw.draw, fg, winx, winy + font->ascent + 1,
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.