Krolyxon
Commit c280129

Branches

Refs →

nsxivc280129

Use Xft for font loading and text drawing

Author
Bert Münnich
Date
2016-08-06 15:27 +0200
Parent
aabc2bd
Commit
c280129cef4ff2e8667b8700c9bdf671fdd7c8ef

+56 −98

8 files changed

  1. M Makefile +3 −3
  2. M README.md +5 −6
  3. M config.def.h +2 −2
  4. M image.c +1 −1
  5. M main.c +2 −2
  6. M thumbs.c +4 −4
  7. M window.c +32 −74
  8. M window.h +7 −6
M Makefile View
@@ -5,9 +5,9 @@ MANPREFIX := $(PREFIX)/share/man
55
66 CC ?= gcc
77 CFLAGS += -std=c99 -Wall -pedantic
8−CPPFLAGS += -I$(PREFIX)/include -D_XOPEN_SOURCE=700
9−LDFLAGS += -L$(PREFIX)/lib
10−LIBS := -lX11 -lImlib2
8+CPPFLAGS += -I/usr/include/freetype2 -D_XOPEN_SOURCE=700
9+LDFLAGS +=
10+LIBS := -lImlib2 -lX11 -lXft
1111
1212 # optional dependencies:
1313 # giflib: gif animations
M README.md View
@@ -2,12 +2,11 @@
22
33 **Simple X Image Viewer**
44
5−sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are
6−imlib2, libexif and giflib. The primary goal for writing sxiv is to create an
7−image viewer, which only has the most basic features required for fast image
8−viewing (the ones I want). It has vi key bindings and works nicely with tiling
9−window managers. Its code base should be kept small and clean to make it easy
10−for you to dig into it and customize it for your needs.
5+The primary goal of sxiv is to create an image viewer, which only has the most
6+basic features required for fast image viewing (the ones I want). It has vi key
7+bindings and works nicely with tiling window managers. Its code base should be
8+kept small and clean to make it easy for you to dig into it and customize it
9+for your needs.
1110
1211
1312 Features
M config.def.h View
@@ -7,9 +7,9 @@ enum {
77 };
88
99 /* bar font:
10− * (see X(7) section "FONT NAMES" for valid values)
10+ * (see fonts-conf(5) subsection "FONT NAMES" for valid values)
1111 */
12−static const char * const BAR_FONT = "-*-fixed-medium-r-*-*-13-*-*-*-*-60-*-*";
12+static const char * const BAR_FONT = "monospace:size=8";
1313
1414 /* colors:
1515 * (see X(7) section "COLOR NAMES" for valid values)
M image.c View
@@ -485,7 +485,7 @@ void img_render(img_t *img)
485485 }
486486 imlib_image_put_back_data(data);
487487 } else {
488− c = win->fullscreen ? win->fscol : win->bgcol;
488+ c = win->fullscreen ? win->fscol.pixel : win->bgcol.pixel;
489489 imlib_context_set_color(c >> 16 & 0xFF, c >> 8 & 0xFF, c & 0xFF, 0xFF);
490490 imlib_image_fill_rectangle(0, 0, dw, dh);
491491 }
M main.c View
@@ -386,8 +386,8 @@ void update_info(void)
386386 if (ow_info) {
387387 fn = strlen(files[fileidx].name);
388388 if (fn < l->size &&
389− win_textwidth(files[fileidx].name, fn, true) +
390− win_textwidth(r->buf, r->p - r->buf, true) < win.w)
389+ win_textwidth(&win.env, files[fileidx].name, fn, true) +
390+ win_textwidth(&win.env, r->buf, r->p - r->buf, true) < win.w)
391391 {
392392 strncpy(l->buf, files[fileidx].name, l->size);
393393 } else {
M thumbs.c View
@@ -480,14 +480,14 @@ void tns_mark(tns_t *tns, int n, bool mark)
480480 if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) {
481481 win_t *win = tns->win;
482482 thumb_t *t = &tns->thumbs[n];
483− unsigned long col = win->fullscreen ? win->fscol : win->bgcol;
483+ unsigned long col = win->fullscreen ? win->fscol.pixel : win->bgcol.pixel;
484484 int x = t->x + t->w, y = t->y + t->h;
485485
486486 win_draw_rect(win, x - 1, y + 1, 1, tns->bw, true, 1, col);
487487 win_draw_rect(win, x + 1, y - 1, tns->bw, 1, true, 1, col);
488488
489489 if (mark)
490− col = win->selcol;
490+ col = win->selcol.pixel;
491491
492492 win_draw_rect(win, x, y, tns->bw + 2, tns->bw + 2, true, 1, col);
493493
@@ -505,9 +505,9 @@ void tns_highlight(tns_t *tns, int n, bool hl)
505505 int oxy = (tns->bw + 1) / 2 + 1, owh = tns->bw + 2;
506506
507507 if (hl)
508− col = win->selcol;
508+ col = win->selcol.pixel;
509509 else
510− col = win->fullscreen ? win->fscol : win->bgcol;
510+ col = win->fullscreen ? win->fscol.pixel : win->bgcol.pixel;
511511
512512 win_draw_rect(win, t->x - oxy, t->y - oxy, t->w + owh, t->h + owh,
513513 false, tns->bw, col);
M window.c View
@@ -41,13 +41,7 @@ static Cursor chand;
4141 static Cursor cwatch;
4242 static GC gc;
4343
44−static struct {
45− int ascent;
46− int descent;
47− XFontStruct *xfont;
48− XFontSet set;
49−} font;
50−
44+static XftFont *font;
5145 static int fontheight;
5246 static int barheight;
5347
@@ -56,50 +50,21 @@ Atom atoms[ATOM_COUNT];
5650 static Bool fs_support;
5751 static Bool fs_warned;
5852
59−void win_init_font(Display *dpy, const char *fontstr)
53+void win_init_font(const win_env_t *e, const char *fontstr)
6054 {
61− int n;
62− char *def, **missing;
63−
64− font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
65− if (missing)
66− XFreeStringList(missing);
67− if (font.set) {
68− XFontStruct **xfonts;
69− char **font_names;
70−
71− font.ascent = font.descent = 0;
72− XExtentsOfFontSet(font.set);
73− n = XFontsOfFontSet(font.set, &xfonts, &font_names);
74− while (n--) {
75− font.ascent = MAX(font.ascent, (*xfonts)->ascent);
76− font.descent = MAX(font.descent,(*xfonts)->descent);
77− xfonts++;
78− }
79− } else {
80− if ((font.xfont = XLoadQueryFont(dpy, fontstr)) == NULL &&
81− (font.xfont = XLoadQueryFont(dpy, "fixed")) == NULL)
82− {
83− error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr);
84− }
85− font.ascent = font.xfont->ascent;
86− font.descent = font.xfont->descent;
87− }
88− fontheight = font.ascent + font.descent;
55+ if ((font = XftFontOpenName(e->dpy, e->scr, fontstr)) == NULL)
56+ error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr);
57+ fontheight = font->ascent + font->descent;
8958 barheight = fontheight + 2 * V_TEXT_PAD;
9059 }
9160
92−unsigned long win_alloc_color(win_t *win, const char *name)
61+void win_alloc_color(const win_env_t *e, const char *name, XftColor *col)
9362 {
94− XColor col;
95−
96− if (XAllocNamedColor(win->env.dpy,
97− DefaultColormap(win->env.dpy, win->env.scr),
98− name, &col, &col) == 0)
63+ if (!XftColorAllocName(e->dpy, DefaultVisual(e->dpy, e->scr),
64+ DefaultColormap(e->dpy, e->scr), name, col))
9965 {
10066 error(EXIT_FAILURE, 0, "Error allocating color '%s'", name);
10167 }
102− return col.pixel;
10368 }
10469
10570 void win_check_wm_support(Display *dpy, Window root)
@@ -155,13 +120,13 @@ void win_init(win_t *win)
155120 if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0)
156121 error(0, 0, "No locale support");
157122
158− win_init_font(e->dpy, BAR_FONT);
123+ win_init_font(e, BAR_FONT);
159124
160− win->bgcol = win_alloc_color(win, WIN_BG_COLOR);
161− win->fscol = win_alloc_color(win, WIN_FS_COLOR);
162− win->selcol = win_alloc_color(win, SEL_COLOR);
163− win->bar.bgcol = win_alloc_color(win, BAR_BG_COLOR);
164− win->bar.fgcol = win_alloc_color(win, BAR_FG_COLOR);
125+ win_alloc_color(e, WIN_BG_COLOR, &win->bgcol);
126+ win_alloc_color(e, WIN_FS_COLOR, &win->fscol);
127+ win_alloc_color(e, SEL_COLOR, &win->selcol);
128+ win_alloc_color(e, BAR_BG_COLOR, &win->bar.bgcol);
129+ win_alloc_color(e, BAR_FG_COLOR, &win->bar.fgcol);
165130
166131 win->bar.l.size = BAR_L_LEN;
167132 win->bar.r.size = BAR_R_LEN;
@@ -295,7 +260,7 @@ void win_open(win_t *win)
295260 win->buf.h = e->scrh;
296261 win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
297262 win->buf.w, win->buf.h, e->depth);
298− XSetForeground(e->dpy, gc, fullscreen ? win->fscol : win->bgcol);
263+ XSetForeground(e->dpy, gc, fullscreen ? win->fscol.pixel : win->bgcol.pixel);
299264 XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
300265 XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm);
301266
@@ -387,7 +352,7 @@ void win_clear(win_t *win)
387352 win->buf.pm = XCreatePixmap(e->dpy, win->xwin,
388353 win->buf.w, win->buf.h, e->depth);
389354 }
390− XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol : win->bgcol);
355+ XSetForeground(e->dpy, gc, win->fullscreen ? win->fscol.pixel : win->bgcol.pixel);
391356 XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
392357 }
393358
@@ -398,33 +363,33 @@ void win_draw_bar(win_t *win)
398363 const char *dots = "...";
399364 win_env_t *e;
400365 win_bar_t *l, *r;
366+ XftDraw *d;
401367
402368 if ((l = &win->bar.l)->buf == NULL || (r = &win->bar.r)->buf == NULL)
403369 return;
404370
405371 e = &win->env;
406− y = win->h + font.ascent + V_TEXT_PAD;
372+ y = win->h + font->ascent + V_TEXT_PAD;
407373 w = win->w;
374+ d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
375+ DefaultColormap(e->dpy, e->scr));
408376
409− XSetForeground(e->dpy, gc, win->bar.bgcol);
377+ XSetForeground(e->dpy, gc, win->bar.bgcol.pixel);
410378 XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->h, win->w, win->bar.h);
411379
412− XSetForeground(e->dpy, gc, win->bar.fgcol);
413− XSetBackground(e->dpy, gc, win->bar.bgcol);
380+ XSetForeground(e->dpy, gc, win->bar.fgcol.pixel);
381+ XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
414382
415383 if ((len = strlen(r->buf)) > 0) {
416− if ((tw = win_textwidth(r->buf, len, true)) > w)
384+ if ((tw = win_textwidth(e, r->buf, len, true)) > w)
417385 return;
418386 x = win->w - tw + H_TEXT_PAD;
419387 w -= tw;
420− if (font.set)
421− XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, r->buf, len);
422− else
423− XDrawString(e->dpy, win->buf.pm, gc, x, y, r->buf, len);
388+ XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)r->buf, len);
424389 }
425390 if ((len = strlen(l->buf)) > 0) {
426391 olen = len;
427− while (len > 0 && (tw = win_textwidth(l->buf, len, true)) > w)
392+ while (len > 0 && (tw = win_textwidth(e, l->buf, len, true)) > w)
428393 len--;
429394 if (len > 0) {
430395 if (len != olen) {
@@ -435,14 +400,12 @@ void win_draw_bar(win_t *win)
435400 memcpy(l->buf + len - w, dots, w);
436401 }
437402 x = H_TEXT_PAD;
438− if (font.set)
439− XmbDrawString(e->dpy, win->buf.pm, font.set, gc, x, y, l->buf, len);
440− else
441− XDrawString(e->dpy, win->buf.pm, gc, x, y, l->buf, len);
403+ XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)l->buf, len);
442404 if (len != olen)
443405 memcpy(l->buf + len - w, rest, w);
444406 }
445407 }
408+ XftDrawDestroy(d);
446409 }
447410
448411 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,
470433 XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h);
471434 }
472435
473−int win_textwidth(const char *text, unsigned int len, bool with_padding)
436+int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding)
474437 {
475− XRectangle r;
476− int padding = with_padding ? 2 * H_TEXT_PAD : 0;
438+ XGlyphInfo ext;
477439
478− if (font.set) {
479− XmbTextExtents(font.set, text, len, NULL, &r);
480− return r.width + padding;
481− } else {
482− return XTextWidth(font.xfont, text, len) + padding;
483− }
440+ XftTextExtentsUtf8(e->dpy, font, (XftChar8*)text, len, &ext);
441+ return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0);
484442 }
485443
486444 void win_set_title(win_t *win, const char *title)
M window.h View
@@ -21,6 +21,7 @@
2121
2222 #include <X11/Xlib.h>
2323 #include <X11/Xutil.h>
24+#include <X11/Xft/Xft.h>
2425
2526 #include "types.h"
2627
@@ -59,9 +60,9 @@ typedef struct {
5960 Window xwin;
6061 win_env_t env;
6162
62− unsigned long bgcol;
63− unsigned long fscol;
64− unsigned long selcol;
63+ XftColor bgcol;
64+ XftColor fscol;
65+ XftColor selcol;
6566
6667 int x;
6768 int y;
@@ -81,8 +82,8 @@ typedef struct {
8182 unsigned int h;
8283 win_bar_t l;
8384 win_bar_t r;
84− unsigned long bgcol;
85− unsigned long fgcol;
85+ XftColor bgcol;
86+ XftColor fgcol;
8687 } bar;
8788 } win_t;
8889
@@ -101,7 +102,7 @@ void win_clear(win_t*);
101102 void win_draw(win_t*);
102103 void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long);
103104
104−int win_textwidth(const char*, unsigned int, bool);
105+int win_textwidth(const win_env_t*, const char*, unsigned int, bool);
105106
106107 void win_set_title(win_t*, const char*);
107108 void win_set_cursor(win_t*, cursor_t);