Blob Blame Raw

#include "app.h"



int graphInit(Graph *g, App *app) {
  LOGDBG("graph: init");
  
  CLEARFROM(g, app);
  g->app = app;
  
  enum {
    F = 0xffffu,   // full
    B = 0x9000u,   // bright
    D = 0x7000u,   // dark
    Q = 0x4000u }; // quart
  static const XRenderColor renderColors[GC_COUNT] = {
    { 0, 0, Q, F },   // window
    { 0, 0, D, F },   // inactive button
    { 0, 0, B, F },   // highlighted button
    { 0, 0, F, F },   // active button
    { B, 0, F, F },   // active button 2
    { F, F, 0, F },   // inactive text
    { F, F, 0, F },   // highlighted 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, int highlight) {
  GraphStyle s = active == 1 ? GC_BUTTON_ACTIVE
               : active == 2 ? GC_BUTTON_ACTIVE2
               : highlight   ? GC_BUTTON_HIGHTLIGHT
               :               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 asc  = tl->g->fonts[i]->ascent;
    int desc = tl->g->fonts[i]->descent;
    int w = e.width;
    int minw = asc + asc/3;
    int h = asc + desc; // proper value is: asc + 2*desc
    
    tl->sizes[i].x = e.x - w/2;
    tl->sizes[i].y = asc/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, int highlight) {
  if (!tl->len) return;
  GraphStyle s = active == 1 ? GC_TEXT_ACTIVE
               : active == 2 ? GC_TEXT_ACTIVE2
               : highlight   ? GC_TEXT_HIGHTLIGHT
               :               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 );
}