214 lines
6.3 KiB
C
214 lines
6.3 KiB
C
/*
|
|
* wfont_x11.c — X11/Xft + PangoXft font backend for WINGs.
|
|
*
|
|
* Per-screen state (ScreenCtxX11): XftDraw + display + screen number.
|
|
* Per-font handle (FontHandleX11): XftFont* + PangoLayout*.
|
|
*/
|
|
|
|
#include "wconfig.h"
|
|
#include "WINGsP.h"
|
|
#include "WINGs/WINGsX11.h"
|
|
|
|
#include <X11/Xft/Xft.h>
|
|
#include <fontconfig/fontconfig.h>
|
|
|
|
#ifdef USE_PANGO
|
|
#include <pango/pangoxft.h>
|
|
#include <pango/pangofc-fontmap.h>
|
|
#endif
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
typedef struct {
|
|
Display *display;
|
|
int screen_num;
|
|
XftDraw *xftdraw;
|
|
#ifdef USE_PANGO
|
|
PangoFontMap *fontmap;
|
|
#endif
|
|
} ScreenCtxX11;
|
|
|
|
typedef struct {
|
|
Display *display; /* needed for XftFontClose / XftTextExtentsUtf8 */
|
|
XftFont *xft;
|
|
#ifdef USE_PANGO
|
|
PangoLayout *layout;
|
|
#endif
|
|
} FontHandleX11;
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void *
|
|
x11_screen_init(W_Screen *scr)
|
|
{
|
|
ScreenCtxX11 *ctx = wmalloc(sizeof(*ctx));
|
|
ctx->display = scr->display;
|
|
ctx->screen_num = scr->screen;
|
|
ctx->xftdraw = XftDrawCreate(scr->display,
|
|
W_DRAWABLE(scr),
|
|
scr->visual,
|
|
scr->colormap);
|
|
#ifdef USE_PANGO
|
|
ctx->fontmap = pango_xft_get_font_map(scr->display, scr->screen);
|
|
#endif
|
|
return ctx;
|
|
}
|
|
|
|
static void
|
|
x11_screen_fini(void *sctx)
|
|
{
|
|
ScreenCtxX11 *ctx = sctx;
|
|
XftDrawDestroy(ctx->xftdraw);
|
|
wfree(ctx);
|
|
}
|
|
|
|
static void *
|
|
x11_font_open(void *sctx, const char *fc_name, int *height_out, int *y_out)
|
|
{
|
|
ScreenCtxX11 *ctx = sctx;
|
|
FontHandleX11 *h = wmalloc(sizeof(*h));
|
|
|
|
h->display = ctx->display;
|
|
h->xft = XftFontOpenName(ctx->display, ctx->screen_num, fc_name);
|
|
if (!h->xft) {
|
|
wfree(h);
|
|
return NULL;
|
|
}
|
|
|
|
*height_out = h->xft->ascent + h->xft->descent;
|
|
*y_out = h->xft->ascent;
|
|
|
|
#ifdef USE_PANGO
|
|
{
|
|
PangoContext *pctx = pango_font_map_create_context(ctx->fontmap);
|
|
FcPattern *pat = FcNameParse((FcChar8 *)fc_name);
|
|
PangoFontDescription *desc = pango_fc_font_description_from_pattern(pat, FALSE);
|
|
double sz = 0;
|
|
|
|
h->layout = pango_layout_new(pctx);
|
|
if (FcPatternGetDouble(pat, FC_PIXEL_SIZE, 0, &sz) == FcResultMatch)
|
|
pango_font_description_set_absolute_size(desc, sz * PANGO_SCALE);
|
|
pango_layout_set_font_description(h->layout, desc);
|
|
|
|
pango_font_description_free(desc);
|
|
FcPatternDestroy(pat);
|
|
g_object_unref(pctx);
|
|
}
|
|
#endif
|
|
|
|
return h;
|
|
}
|
|
|
|
static void
|
|
x11_font_close(void *sctx, void *handle)
|
|
{
|
|
FontHandleX11 *h = handle;
|
|
(void)sctx;
|
|
if (!h) return;
|
|
#ifdef USE_PANGO
|
|
if (h->layout) g_object_unref(h->layout);
|
|
#endif
|
|
XftFontClose(h->display, h->xft);
|
|
wfree(h);
|
|
}
|
|
|
|
static int
|
|
x11_text_width(void *handle, const char *text, int len)
|
|
{
|
|
FontHandleX11 *h = handle;
|
|
#ifdef USE_PANGO
|
|
const char *prev = pango_layout_get_text(h->layout);
|
|
if (!prev || strncmp(text, prev, (size_t)len) != 0 || prev[len] != '\0')
|
|
pango_layout_set_text(h->layout, text, len);
|
|
int w = 0;
|
|
pango_layout_get_pixel_size(h->layout, &w, NULL);
|
|
return w;
|
|
#else
|
|
XGlyphInfo ext;
|
|
XftTextExtentsUtf8(h->display, h->xft, (XftChar8 *)text, len, &ext);
|
|
return ext.xOff;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
x11_draw_string(void *sctx, void *handle, WMDrawable d,
|
|
int x, int y,
|
|
unsigned short r, unsigned short g,
|
|
unsigned short b, unsigned short a,
|
|
unsigned long pixel,
|
|
const char *text, int len)
|
|
{
|
|
ScreenCtxX11 *ctx = sctx;
|
|
FontHandleX11 *h = handle;
|
|
XftColor xc = { .pixel = pixel,
|
|
.color = { .red=r, .green=g, .blue=b, .alpha=a } };
|
|
|
|
XftDrawChange(ctx->xftdraw, (Drawable)d);
|
|
|
|
#ifdef USE_PANGO
|
|
const char *prev = pango_layout_get_text(h->layout);
|
|
if (!prev || strcmp(text, prev) != 0)
|
|
pango_layout_set_text(h->layout, text, len);
|
|
pango_xft_render_layout(ctx->xftdraw, &xc, h->layout,
|
|
x * PANGO_SCALE, y * PANGO_SCALE);
|
|
#else
|
|
XftDrawStringUtf8(ctx->xftdraw, &xc, h->xft,
|
|
x, y + h->xft->ascent,
|
|
(XftChar8 *)text, len);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
x11_draw_image_string(void *sctx, void *handle, WMDrawable d,
|
|
int x, int y,
|
|
unsigned short tr, unsigned short tg,
|
|
unsigned short tb, unsigned short ta, unsigned long tpix,
|
|
unsigned short br, unsigned short bg,
|
|
unsigned short bb, unsigned short ba, unsigned long bpix,
|
|
int bg_w, int bg_h,
|
|
const char *text, int len)
|
|
{
|
|
ScreenCtxX11 *ctx = sctx;
|
|
FontHandleX11 *h = handle;
|
|
XftColor tc = { .pixel = tpix,
|
|
.color = { .red=tr, .green=tg, .blue=tb, .alpha=ta } };
|
|
XftColor bc = { .pixel = bpix,
|
|
.color = { .red=br, .green=bg, .blue=bb, .alpha=ba } };
|
|
|
|
XftDrawChange(ctx->xftdraw, (Drawable)d);
|
|
XftDrawRect(ctx->xftdraw, &bc, x, y, (unsigned)bg_w, (unsigned)bg_h);
|
|
|
|
#ifdef USE_PANGO
|
|
const char *prev = pango_layout_get_text(h->layout);
|
|
if (!prev || strcmp(text, prev) != 0)
|
|
pango_layout_set_text(h->layout, text, len);
|
|
pango_xft_render_layout(ctx->xftdraw, &tc, h->layout,
|
|
x * PANGO_SCALE, y * PANGO_SCALE);
|
|
#else
|
|
XftDrawStringUtf8(ctx->xftdraw, &tc, h->xft,
|
|
x, y + h->xft->ascent,
|
|
(XftChar8 *)text, len);
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
x11_lookup_string(void *sctx, W_View *view, WMEvent *event,
|
|
char *buffer, int buflen, unsigned long *keysym_out)
|
|
{
|
|
(void)sctx;
|
|
if (!event->_x11_raw) { *keysym_out = 0; return 0; }
|
|
return W_LookupString(view, &((XEvent *)event->_x11_raw)->xkey,
|
|
buffer, buflen, (KeySym *)keysym_out, NULL);
|
|
}
|
|
|
|
const W_FontBackend W_FontBackendX11 = {
|
|
.screen_init = x11_screen_init,
|
|
.screen_fini = x11_screen_fini,
|
|
.font_open = x11_font_open,
|
|
.font_close = x11_font_close,
|
|
.text_width = x11_text_width,
|
|
.draw_string = x11_draw_string,
|
|
.draw_image_string = x11_draw_image_string,
|
|
.lookup_string = x11_lookup_string,
|
|
};
|