commit c280129cef4ff2e8667b8700c9bdf671fdd7c8ef
Author:     Bert Münnich <[email protected]>
AuthorDate: Sat Aug 6 15:27:58 2016 +0200
Commit:     Bert Münnich <[email protected]>
CommitDate: Sat Aug 6 15:27:58 2016 +0200

    Use Xft for font loading and text drawing

diff --git a/Makefile b/Makefile
index 2c39905..fc75c00 100644
--- a/Makefile
+++ b/Makefile
@@ -5,9 +5,9 @@ MANPREFIX := $(PREFIX)/share/man
 
 CC        ?= gcc
 CFLAGS    += -std=c99 -Wall -pedantic
-CPPFLAGS  += -I$(PREFIX)/include -D_XOPEN_SOURCE=700
-LDFLAGS   += -L$(PREFIX)/lib
-LIBS      := -lX11 -lImlib2
+CPPFLAGS  += -I/usr/include/freetype2 -D_XOPEN_SOURCE=700
+LDFLAGS   += 
+LIBS      := -lImlib2 -lX11 -lXft
 
 # optional dependencies:
 # giflib: gif animations
diff --git a/README.md b/README.md
index dfb29b8..28334b0 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,11 @@
 
 **Simple X Image Viewer**
 
-sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are
-imlib2, libexif and giflib. The primary goal for writing sxiv is to create an
-image viewer, which only has the most basic features required for fast image
-viewing (the ones I want). It has vi key bindings and works nicely with tiling
-window managers.  Its code base should be kept small and clean to make it easy
-for you to dig into it and customize it for your needs.
+The primary goal of sxiv is to create an image viewer, which only has the most
+basic features required for fast image viewing (the ones I want). It has vi key
+bindings and works nicely with tiling window managers.  Its code base should be
+kept small and clean to make it easy for you to dig into it and customize it
+for your needs.
 
 
 Features
diff --git a/config.def.h b/config.def.h
index f3cc71e..bfa1338 100644
--- a/config.def.h
+++ b/config.def.h
@@ -7,9 +7,9 @@ enum {
 };
 
 /* bar font:
- * (see X(7) section "FONT NAMES" for valid values)
+ * (see fonts-conf(5) subsection "FONT NAMES" for valid values)
  */
-static const char * const BAR_FONT = "-*-fixed-medium-r-*-*-13-*-*-*-*-60-*-*";
+static const char * const BAR_FONT = "monospace:size=8";
 
 /* colors:
  * (see X(7) section "COLOR NAMES" for valid values)
diff --git a/image.c b/image.c
index 9350ab1..ebd522d 100644
--- a/image.c
+++ b/image.c
@@ -485,7 +485,7 @@ void img_render(img_t *img)
                        }
                        imlib_image_put_back_data(data);
                } else {
-                       c = win->fullscreen ? win->fscol : win->bgcol;
+                       c = win->fullscreen ? win->fscol.pixel : 
win->bgcol.pixel;
                        imlib_context_set_color(c >> 16 & 0xFF, c >> 8 & 0xFF, 
c & 0xFF, 0xFF);
                        imlib_image_fill_rectangle(0, 0, dw, dh);
                }
diff --git a/main.c b/main.c
index 361477e..5b41170 100644
--- a/main.c
+++ b/main.c
@@ -386,8 +386,8 @@ void update_info(void)
        if (ow_info) {
                fn = strlen(files[fileidx].name);
                if (fn < l->size &&
-                   win_textwidth(files[fileidx].name, fn, true) +
-                   win_textwidth(r->buf, r->p - r->buf, true) < win.w)
+                   win_textwidth(&win.env, files[fileidx].name, fn, true) +
+                   win_textwidth(&win.env, r->buf, r->p - r->buf, true) < 
win.w)
                {
                        strncpy(l->buf, files[fileidx].name, l->size);
                } else {
diff --git a/thumbs.c b/thumbs.c
index bfce2ff..f51f85f 100644
--- a/thumbs.c
+++ b/thumbs.c
@@ -480,14 +480,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
        if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) {
                win_t *win = tns->win;
                thumb_t *t = &tns->thumbs[n];
-               unsigned long col = win->fullscreen ? win->fscol : win->bgcol;
+               unsigned long col = win->fullscreen ? win->fscol.pixel : 
win->bgcol.pixel;
                int x = t->x + t->w, y = t->y + t->h;
 
                win_draw_rect(win, x - 1, y + 1, 1, tns->bw, true, 1, col);
                win_draw_rect(win, x + 1, y - 1, tns->bw, 1, true, 1, col);
 
                if (mark)
-                       col = win->selcol;
+                       col = win->selcol.pixel;
 
                win_draw_rect(win, x, y, tns->bw + 2, tns->bw + 2, true, 1, 
col);
 
@@ -505,9 +505,9 @@ void tns_highlight(tns_t *tns, int n, bool hl)
                int oxy = (tns->bw + 1) / 2 + 1, owh = tns->bw + 2;
 
                if (hl)
-                       col = win->selcol;
+                       col = win->selcol.pixel;
                else
-                       col = win->fullscreen ? win->fscol : win->bgcol;
+                       col = win->fullscreen ? win->fscol.pixel : 
win->bgcol.pixel;
 
                win_draw_rect(win, t->x - oxy, t->y - oxy, t->w + owh, t->h + 
owh,
                              false, tns->bw, col);
diff --git a/window.c b/window.c
index 696c2ea..ad08787 100644
--- a/window.c
+++ b/window.c
@@ -41,13 +41,7 @@ static Cursor chand;
 static Cursor cwatch;
 static GC gc;
 
-static struct {
-       int ascent;
-       int descent;
-       XFontStruct *xfont;
-       XFontSet set;
-} font;
-
+static XftFont *font;
 static int fontheight;
 static int barheight;
 
@@ -56,50 +50,21 @@ Atom atoms[ATOM_COUNT];
 static Bool fs_support;
 static Bool fs_warned;
 
-void win_init_font(Display *dpy, const char *fontstr)
+void win_init_font(const win_env_t *e, const char *fontstr)
 {
-       int n;
-       char *def, **missing;
-
-       font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
-       if (missing)
-               XFreeStringList(missing);
-       if (font.set) {
-               XFontStruct **xfonts;
-               char **font_names;
-
-               font.ascent = font.descent = 0;
-               XExtentsOfFontSet(font.set);
-               n = XFontsOfFontSet(font.set, &xfonts, &font_names);
-               while (n--) {
-                       font.ascent  = MAX(font.ascent, (*xfonts)->ascent);
-                       font.descent = MAX(font.descent,(*xfonts)->descent);
-                       xfonts++;
-               }
-       } else {
-               if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL &&
-                   (font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL)
-               {
-                       error(EXIT_FAILURE, 0, "Error loading font '%s'", 
fontstr);
-               }
-               font.ascent  = font.xfont->ascent;
-               font.descent = font.xfont->descent;
-       }
-       fontheight = font.ascent + font.descent;
+       if ((font = XftFontOpenName(e->dpy, e->scr, fontstr)) == NULL)
+               error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr);
+       fontheight = font->ascent + font->descent;
        barheight = fontheight + 2 * V_TEXT_PAD;
 }
 
-unsigned long win_alloc_color(win_t *win, const char *name)
+void win_alloc_color(const win_env_t *e, const char *name, XftColor *col)
 {
-       XColor col;
-
-       if (XAllocNamedColor(win->env.dpy,
-                            DefaultColormap(win->env.dpy, win->env.scr),
-                            name, &col, &col) == 0)
+       if (!XftColorAllocName(e->dpy, DefaultVisual(e->dpy, e->scr),
+                              DefaultColormap(e->dpy, e->scr), name, col))
        {
                error(EXIT_FAILURE, 0, "Error allocating color '%s'", name);
        }
-       return col.pixel;
 }
 
 void win_check_wm_support(Display *dpy, Window root)
@@ -155,13 +120,13 @@ void win_init(win_t *win)
        if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
                error(0, 0, "No locale support");
 
-       win_init_font(e->dpy, BAR_FONT);
+       win_init_font(e, BAR_FONT);
 
-       win->bgcol     = win_alloc_color(win, WIN_BG_COLOR);
-       win->fscol     = win_alloc_color(win, WIN_FS_COLOR);
-       win->selcol    = win_alloc_color(win, SEL_COLOR);
-       win->bar.bgcol = win_alloc_color(win, BAR_BG_COLOR);
-       win->bar.fgcol = win_alloc_color(win, BAR_FG_COLOR);
+       win_alloc_color(e, WIN_BG_COLOR, &win->bgcol);
+       win_alloc_color(e, WIN_FS_COLOR, &win->fscol);
+       win_alloc_color(e, SEL_COLOR,    &win->selcol);
+       win_alloc_color(e, BAR_BG_COLOR, &win->bar.bgcol);
+       win_alloc_color(e, BAR_FG_COLOR, &win->bar.fgcol);
 
        win->bar.l.size = BAR_L_LEN;
        win->bar.r.size = BAR_R_LEN;
@@ -295,7 +260,7 @@ void win_open(win_t *win)
        win->buf.h = e->scrh;
        win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
                                    win->buf.w, win->buf.h, e->depth);
-       XSetForeground(e->dpy, gc, fullscreen ? win->fscol : win->bgcol);
+       XSetForeground(e->dpy, gc, fullscreen ? win->fscol.pixel : 
win->bgcol.pixel);
        XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
        XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm);
 
@@ -387,7 +352,7 @@ void win_clear(win_t *win)
                win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
                                            win->buf.w, win->buf.h, e->depth);
        }
-       XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol);
+       XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol.pixel : 
win->bgcol.pixel);
        XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
 }
 
@@ -398,33 +363,33 @@ void win_draw_bar(win_t *win)
        const char *dots = "...";
        win_env_t *e;
        win_bar_t *l, *r;
+       XftDraw *d;
 
        if ((l = &win->bar.l)->buf == NULL || (r = &win->bar.r)->buf == NULL)
                return;
 
        e = &win->env;
-       y = win->h + font.ascent + V_TEXT_PAD;
+       y = win->h + font->ascent + V_TEXT_PAD;
        w = win->w;
+       d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
+                         DefaultColormap(e->dpy, e->scr));
 
-       XSetForeground(e->dpy, gc, win->bar.bgcol);
+       XSetForeground(e->dpy, gc, win->bar.bgcol.pixel);
        XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h);
 
-       XSetForeground(e->dpy, gc, win->bar.fgcol);
-       XSetBackground(e->dpy, gc, win->bar.bgcol);
+       XSetForeground(e->dpy, gc, win->bar.fgcol.pixel);
+       XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
 
        if ((len = strlen(r->buf)) > 0) {
-               if ((tw = win_textwidth(r->buf, len, true)) > w)
+               if ((tw = win_textwidth(e, r->buf, len, true)) > w)
                        return;
                x = win->w - tw + H_TEXT_PAD;
                w -= tw;
-               if (font.set)
-                       XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, 
r->buf, len);
-               else
-                       XDrawString(e->dpy, win->buf.pm, gc, x, y, r->buf, len);
+               XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, 
(XftChar8*)r->buf, len);
        }
        if ((len = strlen(l->buf)) > 0) {
                olen = len;
-               while (len > 0 && (tw = win_textwidth(l->buf, len, true)) > w)
+               while (len > 0 && (tw = win_textwidth(e, l->buf, len, true)) > 
w)
                        len--;
                if (len > 0) {
                        if (len != olen) {
@@ -435,14 +400,12 @@ void win_draw_bar(win_t *win)
                                memcpy(l->buf + len - w, dots, w);
                        }
                        x = H_TEXT_PAD;
-                       if (font.set)
-                               XmbDrawString(e->dpy, win->buf.pm, font.set, 
gc, x, y, l->buf, len);
-                       else
-                               XDrawString(e->dpy, win->buf.pm, gc, x, y, 
l->buf, len);
+                       XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, 
(XftChar8*)l->buf, len);
                        if (len != olen)
                          memcpy(l->buf + len - w, rest, w);
                }
        }
+       XftDrawDestroy(d);
 }
 
 void win_draw(win_t *win)
@@ -470,17 +433,12 @@ void win_draw_rect(win_t *win, int x, int y, int w, int 
h, bool fill, int lw,
                XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h);
 }
 
-int win_textwidth(const char *text, unsigned int len, bool with_padding)
+int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool 
with_padding)
 {
-       XRectangle r;
-       int padding = with_padding ? 2 * H_TEXT_PAD : 0;
+       XGlyphInfo ext;
 
-       if (font.set) {
-               XmbTextExtents(font.set, text, len, NULL, &r);
-               return r.width + padding;
-       } else {
-               return XTextWidth(font.xfont, text, len) + padding;
-       }
+       XftTextExtentsUtf8(e->dpy, font, (XftChar8*)text, len, &ext);
+       return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0);
 }
 
 void win_set_title(win_t *win, const char *title)
diff --git a/window.h b/window.h
index 31bd898..f5f9df0 100644
--- a/window.h
+++ b/window.h
@@ -21,6 +21,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <X11/Xft/Xft.h>
 
 #include "types.h"
 
@@ -59,9 +60,9 @@ typedef struct {
        Window xwin;
        win_env_t env;
 
-       unsigned long bgcol;
-       unsigned long fscol;
-       unsigned long selcol;
+       XftColor bgcol;
+       XftColor fscol;
+       XftColor selcol;
 
        int x;
        int y;
@@ -81,8 +82,8 @@ typedef struct {
                unsigned int h;
                win_bar_t l;
                win_bar_t r;
-               unsigned long bgcol;
-               unsigned long fgcol;
+               XftColor bgcol;
+               XftColor fgcol;
        } bar;
 } win_t;
 
@@ -101,7 +102,7 @@ void win_clear(win_t*);
 void win_draw(win_t*);
 void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long);
 
-int win_textwidth(const char*, unsigned int, bool);
+int win_textwidth(const win_env_t*, const char*, unsigned int, bool);
 
 void win_set_title(win_t*, const char*);
 void win_set_cursor(win_t*, cursor_t);

Reply via email to