aboutsummaryrefslogblamecommitdiffstats
path: root/font.c
blob: 403466b649bca4b84fd5f7477bc96fb249af0b19 (plain) (tree)






























































































































































                                                                                
/*
 * font.c - cwm font abstraction
 *
 * Copyright (c) 2005 Marius Eriksen <marius@monkey.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "hash.h"
#include "headers.h"
#include "calmwm.h"

static XftFont *_make_font(struct screen_ctx *sc, struct fontdesc *fdp);

HASH_GENERATE(fonthash, fontdesc, node, fontdesc_cmp);

int
fontdesc_cmp(struct fontdesc *a, struct fontdesc *b)
{
	return strcmp(a->name, b->name);
}

/*
 * Fowler/Noll/Vo hash
 *    http://www.isthe.com/chongo/tech/comp/fnv/
 */

#define FNV_P_32 ((unsigned int)0x01000193) /* 16777619 */
#define FNV_1_32 ((unsigned int)0x811c9dc5) /* 2166136261 */

unsigned int
fontdesc_hash(struct fontdesc *fdp)
{
        const unsigned char *p, *end, *start;
        unsigned int hash = FNV_1_32;

	start = fdp->name;
	end = (const unsigned char *)fdp->name + strlen(fdp->name);

        for (p = start; p < end; p++) {
                hash *= FNV_P_32;
                hash ^= (unsigned int)*p;
        }

        return (hash);
}

void
font_init(struct screen_ctx *sc)
{
	XColor xcolor, tmp;

	HASH_INIT(&sc->fonthash, fontdesc_hash);
	sc->xftdraw = XftDrawCreate(G_dpy, sc->rootwin,
	    DefaultVisual(G_dpy, sc->which), DefaultColormap(G_dpy, sc->which));
	if (sc->xftdraw == NULL)
		errx(1, "XftDrawCreate");

	if (!XAllocNamedColor(G_dpy, DefaultColormap(G_dpy, sc->which),
		"black", &xcolor, &tmp))
		errx(1, "XAllocNamedColor");

	sc->xftcolor.color.red = xcolor.red;
	sc->xftcolor.color.green = xcolor.green;
	sc->xftcolor.color.blue = xcolor.blue;
	sc->xftcolor.color.alpha = 0x00ff00;
	sc->xftcolor.pixel = xcolor.pixel;
}

struct fontdesc *
font_getx(struct screen_ctx *sc, const char *name)
{
	struct fontdesc *fdp;

	if ((fdp = font_get(sc, name)) == NULL)
		errx(1, "font_get()");

	return (fdp);
}

struct fontdesc *
font_get(struct screen_ctx *sc, const char *name)
{
	struct fontdesc fd, *fdp;
	XftFont *fn;

	fd.name = name;

	if ((fdp = HASH_FIND(fonthash, &sc->fonthash, &fd)) == NULL
	    && (fn = _make_font(sc, &fd)) != NULL) {
		fdp = xmalloc(sizeof(*fdp));
		fdp->name = xstrdup(fd.name);
		fdp->fn = fn;
		fdp->sc = sc;
		HASH_INSERT(fonthash, &sc->fonthash, fdp);
	}

	return (fdp);
}

int
font_width(struct fontdesc *fdp, const char *text, int len)
{
    XGlyphInfo extents;
    XftTextExtents8(G_dpy, fdp->fn, (const XftChar8*)text, len, &extents);

    return (extents.xOff);
}

void
font_draw(struct fontdesc *fdp, const char *text, int len,
    Drawable d, int x, int y)
{
	XftDrawChange(fdp->sc->xftdraw, d);
	/* Really needs to be UTF8'd. */
	XftDrawString8(fdp->sc->xftdraw, &fdp->sc->xftcolor, fdp->fn, x, y,
	    (const FcChar8*)text, len);
}

int
font_ascent(struct fontdesc *fdp)
{
	return fdp->fn->ascent;
}

int
font_descent(struct fontdesc *fdp)
{
	return fdp->fn->descent;
}

static XftFont *
_make_font(struct screen_ctx *sc, struct fontdesc *fdp)
{
	XftFont *fn = NULL;
	FcPattern *pat, *patx;
	XftResult res;

	if ((pat = FcNameParse(fdp->name)) == NULL)
		return (NULL);

	if ((patx = XftFontMatch(G_dpy, sc->which, pat, &res)) != NULL)
		fn = XftFontOpenPattern(G_dpy, patx);

	FcPatternDestroy(pat);

	return (fn);
}