--- drw.c | 147 +++++++++++++++++++++++++++++++++++------------------------------- drw.h | 17 ++++---- 2 files changed, 86 insertions(+), 78 deletions(-) diff --git a/drw.c b/drw.c index 88d4eac..0adf33e 100644 --- a/drw.c +++ b/drw.c _AT_@ -73,7 +73,6 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->h = h; drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); drw->gc = XCreateGC(dpy, root, 0, NULL); - drw->fontcount = 0; XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; _AT_@ -92,44 +91,39 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) void drw_free(Drw *drw) { - size_t i; - - for (i = 0; i < drw->fontcount; i++) - drw_font_free(drw->fonts[i]); XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); free(drw); } /* This function is an implementation detail. Library users should use - * drw_font_create instead. + * drw_fontset_create instead. */ static Fnt * -drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) { Fnt *font; XftFont *xfont = NULL; FcPattern *pattern = NULL; if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield same - * the same substitution results as using the pattern returned by + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in - * missing-character-rectangles being drawn, at least with some fonts. - */ + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); return NULL; } if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot load font: '%s'\n", fontname); + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); XftFontClose(drw->dpy, xfont); return NULL; } } else if (fontpattern) { if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font pattern.\n"); + fprintf(stderr, "error, cannot load font from pattern.\n"); return NULL; } } else { _AT_@ -139,37 +133,14 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; - font->ascent = xfont->ascent; - font->descent = xfont->descent; - font->h = font->ascent + font->descent; + font->h = xfont->ascent + xfont->descent; font->dpy = drw->dpy; return font; } -Fnt* -drw_font_create(Drw *drw, const char *fontname) -{ - return drw_font_xcreate(drw, fontname, NULL); -} - -void -drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) -{ - size_t i; - Fnt *font; - - for (i = 0; i < fontcount; i++) { - if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { - die("font cache exhausted.\n"); - } else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) { - drw->fonts[drw->fontcount++] = font; - } - } -} - -void -drw_font_free(Fnt *font) +static void +xfont_free(Fnt *font) { if (!font) return; _AT_@ -179,6 +150,33 @@ drw_font_free(Fnt *font) free(font); } +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + void drw_clr_create(Drw *drw, XftColor *dest, const char *clrname) { _AT_@ -209,6 +207,13 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) } void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void drw_setscheme(Drw *drw, Scm scm) { if (drw) _AT_@ -234,7 +239,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex int tx, ty, th; unsigned int ew; XftDraw *d = NULL; - Fnt *curfont, *nextfont; + Fnt *usedfont, *curfont, *nextfont; size_t i, len; int utf8strlen, utf8charlen, render = x || y || w || h; long utf8codepoint = 0; _AT_@ -245,7 +250,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex XftResult result; int charexists = 0; - if ((render && !drw->scheme) || !drw->fontcount) + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0; if (!render) { _AT_@ -259,37 +264,37 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex DefaultColormap(drw->dpy, drw->screen)); } - curfont = drw->fonts[0]; + usedfont = drw->fonts; while (1) { utf8strlen = 0; utf8str = text; nextfont = NULL; while (*text) { utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (i = 0; i < drw->fontcount; i++) { - charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); if (charexists) { - if (drw->fonts[i] == curfont) { + if (curfont == usedfont) { utf8strlen += utf8charlen; text += utf8charlen; } else { - nextfont = drw->fonts[i]; + nextfont = curfont; } break; } } - if (!charexists || (nextfont && nextfont != curfont)) + if (!charexists || nextfont) break; else charexists = 0; } if (utf8strlen) { - drw_font_getexts(curfont, utf8str, utf8strlen, &ew, NULL); + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (ew > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) - drw_font_getexts(curfont, utf8str, len, &ew, NULL); + for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (ew > w - usedfont->h || w < usedfont->h); len--) + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); if (len) { memcpy(buf, utf8str, len); _AT_@ -298,10 +303,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex for (i = len; i && i > len - 3; buf[--i] = '.'); if (render) { - th = curfont->ascent + curfont->descent; - ty = y + (h / 2) - (th / 2) + curfont->ascent; + th = usedfont->h; + ty = y + (h - th) / 2 + usedfont->xfont->ascent; tx = x + (h / 2); - XftDrawStringUtf8(d, invert ? &drw->scheme[ColBg] : &drw->scheme[ColFg], curfont->xfont, tx, ty, (XftChar8 *)buf, len); + XftDrawStringUtf8(d, invert ? &drw->scheme[ColBg] : &drw->scheme[ColFg], usedfont->xfont, tx, ty, (XftChar8 *)buf, len); } x += ew; w -= ew; _AT_@ -312,26 +317,22 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex break; } else if (nextfont) { charexists = 0; - curfont = nextfont; + usedfont = nextfont; } else { /* Regardless of whether or not a fallback font is found, the * character must be drawn. */ charexists = 1; - if (drw->fontcount >= DRW_FONT_CACHE_SIZE) - continue; - fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, utf8codepoint); - if (!drw->fonts[0]->pattern) { - /* Refer to the comment in drw_font_xcreate for more - * information. */ + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ die("the first font in the cache must be loaded from a font string.\n"); } - fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern); + fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); _AT_@ -343,12 +344,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex FcPatternDestroy(fcpattern); if (match) { - curfont = drw_font_xcreate(drw, NULL, match); - if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { - drw->fonts[drw->fontcount++] = curfont; + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* just find the end of the linked list */ + curfont->next = usedfont; } else { - drw_font_free(curfont); - curfont = drw->fonts[0]; + xfont_free(usedfont); + usedfont = drw->fonts; } } } _AT_@ -366,6 +369,14 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) XSync(drw->dpy, False); } +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, text, 0); +} + void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { diff --git a/drw.h b/drw.h index 8ce6bc5..c221780 100644 --- a/drw.h +++ b/drw.h _AT_@ -1,17 +1,15 @@ /* See LICENSE file for copyright and license details. */ -#define DRW_FONT_CACHE_SIZE 32 typedef struct { Cursor cursor; } Cur; -typedef struct { +typedef struct Fnt { Display *dpy; - int ascent; - int descent; unsigned int h; XftFont *xfont; FcPattern *pattern; + struct Fnt *next; } Fnt; enum { ColFg, ColBg, ColCount }; /* Scm index */ _AT_@ -25,8 +23,7 @@ typedef struct { Drawable drawable; GC gc; Scm scheme; - size_t fontcount; - Fnt *fonts[DRW_FONT_CACHE_SIZE]; + Fnt *fonts; } Drw; /* Drawable abstraction */ _AT_@ -35,9 +32,9 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ -Fnt *drw_font_create(Drw *drw, const char *fontname); -void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount); -void drw_font_free(Fnt *font); +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); /* Colorscheme abstraction */ _AT_@ -49,7 +46,7 @@ Cur *drw_cur_create(Drw *drw, int shape); void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ -void drw_setfont(Drw *drw, Fnt *font); +void drw_setfontset(Drw *drw, Fnt *set); void drw_setscheme(Drw *drw, Scm scm); /* Drawing functions */ -- 2.7.3Received on Sun May 22 2016 - 22:29:23 CEST
This archive was generated by hypermail 2.3.0 : Sun May 22 2016 - 22:36:29 CEST