#include "app.h"
int graphInit(Graph *g, App *app) {
LOGDBG("graph: init");
CLEARFROM(g, app);
g->app = app;
enum {
F = 65535u, // full
H = 32768u, // half
Q = 16384u }; // quart
static const XRenderColor renderColors[GC_COUNT] = {
{ 0, 0, Q, F }, // window
{ 0, 0, H, F }, // inactive button
{ 0, 0, F, F }, // active button
{ H, 0, F, F }, // active button 2
{ F, F, 0, F }, // inactive text
{ F, F, 0, F }, // active text
{ F, F, 0, F } }; // active text 2
static const char *fonts[] = FONTS;
static const int sizes[FONT_MAX_SIZES] = FONT_SIZES;
LOGDBG("graph: init: create XftDraw");
g->draw = XftDrawCreate(
g->app->dpy,
g->app->win,
DefaultVisual(g->app->dpy, g->app->screen),
DefaultColormap(g->app->dpy, g->app->screen) );
if (!g->draw)
return LOGERR("graph: init: cannot create XftDraw");
LOGDBG("graph: init: open fonts");
char buf[1024] = {};
for(int i = 0; i < FONT_MAX_SIZES; ++i) {
if (!sizes[i]) break;
for(int j = 0; j < COUNTOF(fonts); ++j) {
snprintf(buf, sizeof(buf), "%s:size=%d", fonts[j], sizes[i]);
LOGDBG("graph: init: try open font [%s]", buf);
g->fonts[g->fontsCnt] = XftFontOpenName(g->app->dpy, g->app->screen, buf);
if (g->fonts[g->fontsCnt]) {
++g->fontsCnt;
break;
} else {
LOGDBG("graph: init: cannot open font [%s]", buf);
}
}
}
if (!g->fontsCnt) {
LOGERR("graph: init: cannot open any font");
XftDrawDestroy(g->draw);
CLEARFROM(g, app);
return 0;
}
LOGDBG("graph: init: allocate colors");
for(int i = 0; i < GC_COUNT; ++i) {
XftColorAllocValue(
g->app->dpy,
DefaultVisual(g->app->dpy, g->app->screen),
DefaultColormap(g->app->dpy, g->app->screen),
&renderColors[i],
&g->colors[i] );
}
return 1;
}
void graphDeinit(Graph *g) {
LOGDBG("graph: deinit");
for(int i = 0; i < GC_COUNT; ++i)
XftColorFree(
g->app->dpy,
DefaultVisual(g->app->dpy, g->app->screen),
DefaultColormap(g->app->dpy, g->app->screen),
&g->colors[i] );
for(int i = 0; i < g->fontsCnt; ++i)
XftFontClose(g->app->dpy, g->fonts[i]);
XftDrawDestroy(g->draw);
}
void graphResize(Graph *g)
{ }
void graphDrawBackgound(Graph *g, int x, int y, int w, int h) {
XftDrawRect(g->draw, &g->colors[GC_WINDOW], x, y, w, h);
}
void graphDrawButton(Graph *g, int x, int y, int w, int h, int active) {
GraphStyle s = active == 1 ? GC_BUTTON_ACTIVE
: active == 2 ? GC_BUTTON_ACTIVE2
: GC_BUTTON_INACTIVE;
XftDrawRect(g->draw, &g->colors[s], x, y, w, h);
}
void textLayoutInit(TextLayout *tl, Graph *g, const char *text) {
CLEARFROM(tl, g);
tl->g = g;
tl->len = text ? strlen(text) : 0;
tl->text = text;
if (!tl->len)
return;
for(int i = 0; i < tl->g->fontsCnt; ++i) {
XGlyphInfo e = {};
XftTextExtentsUtf8(g->app->dpy, g->fonts[i], (const FcChar8*)tl->text, tl->len, &e);
int w = e.width;
int h = tl->g->fonts[i]->ascent;
int minw = h + h/3;
tl->sizes[i].x = -e.x - w/2;
tl->sizes[i].y = h/2;
tl->sizes[i].w = w < minw ? minw : w;
tl->sizes[i].h = h;
}
}
void textLayoutDeinit(TextLayout *tl)
{ CLEARFROM(tl, g); }
void textLayoutDraw(TextLayout *tl, int x, int y, int w, int h, int active) {
if (!tl->len) return;
GraphStyle s = active == 1 ? GC_TEXT_ACTIVE
: active == 2 ? GC_TEXT_ACTIVE2
: GC_TEXT_INACTIVE;
// find font size
int i;
for(i = tl->g->fontsCnt - 1; i > 0; --i)
if (tl->sizes[i].w <= w && tl->sizes[i].h <= h) break;
XftDrawStringUtf8(
tl->g->draw,
&tl->g->colors[s],
tl->g->fonts[i],
x + tl->sizes[i].x,
y + tl->sizes[i].y,
(const FcChar8*)tl->text,
tl->len );
}