|
|
452870 |
|
|
|
452870 |
#include "app.h"
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
int graphInit(Graph *g, App *app) {
|
|
|
452870 |
LOGDBG("graph: init");
|
|
|
452870 |
|
|
|
452870 |
const uint16_t F = 65535; // full
|
|
|
452870 |
const uint16_t H = 32768; // half
|
|
|
452870 |
const uint16_t Q = 16384; // quart
|
|
|
452870 |
const uint16_t colorsRgb[GS_COUNT*2][3] = { // background, foreground
|
|
|
452870 |
{ 0, 0, Q }, { 0, 0, Q }, // window
|
|
|
452870 |
{ 0, 0, H }, { 0, 0, H }, // inactive button
|
|
|
452870 |
{ 0, 0, F }, { 0, 0, F }, // active button
|
|
|
452870 |
{ 0, 0, H }, { F, F, 0 }, // inactive text
|
|
|
452870 |
{ 0, 0, F }, { F, F, 0 } }; // active text
|
|
|
452870 |
|
|
|
452870 |
// create palette
|
|
|
452870 |
g->app = app;
|
|
|
452870 |
g->cm = xcb_generate_id(g->app->xcb);
|
|
|
452870 |
xcb_create_colormap(g->app->xcb, XCB_COLORMAP_ALLOC_NONE, g->cm, g->app->win, g->app->screen->root_visual);
|
|
|
452870 |
|
|
|
452870 |
// encqueue colors allocarion requests
|
|
|
452870 |
xcb_alloc_color_cookie_t cookies[GS_COUNT*2];
|
|
|
452870 |
for(int i = 0; i < GS_COUNT*2; ++i)
|
|
|
452870 |
cookies[i] = xcb_alloc_color(g->app->xcb, g->cm, colorsRgb[i][0], colorsRgb[i][1], colorsRgb[i][2]);
|
|
|
452870 |
|
|
|
452870 |
// take color allocation replies (take color indices)
|
|
|
452870 |
uint32_t colors[GS_COUNT*2];
|
|
|
452870 |
for(int i = 0; i < GS_COUNT*2; ++i) {
|
|
|
452870 |
xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(g->app->xcb, cookies[i], NULL);
|
|
|
452870 |
colors[i] = reply->pixel;
|
|
|
452870 |
free(reply);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
// associate palette with the window
|
|
|
452870 |
xcb_change_window_attributes(g->app->xcb, g->app->win, XCB_CW_COLORMAP, &g->cm);
|
|
|
452870 |
|
|
|
061fcf |
char fontname[1024] = "fixed";
|
|
|
061fcf |
{ // scan fonts
|
|
|
061fcf |
int found = 0;
|
|
|
061fcf |
int maxcnt = 1024;
|
|
|
061fcf |
const char *pattern = "*misc*medium-r-normal*-c-0-ISO10646-1*";
|
|
|
061fcf |
LOGDBG("graph: init: scan fonts by pattern [%s], maxcnt=%d", pattern, maxcnt);
|
|
|
061fcf |
xcb_list_fonts_cookie_t c = xcb_list_fonts(g->app->xcb, maxcnt, strlen(pattern), pattern);
|
|
|
061fcf |
xcb_list_fonts_reply_t *r = xcb_list_fonts_reply(g->app->xcb, c, NULL);
|
|
|
061fcf |
if (r) {
|
|
|
061fcf |
int cnt = xcb_list_fonts_names_length(r);
|
|
|
061fcf |
LOGDBG("graph: init: found %d fonts", cnt);
|
|
|
061fcf |
xcb_str_iterator_t it = xcb_list_fonts_names_iterator(r);
|
|
|
061fcf |
for(int i = 0; i < cnt; ++i) {
|
|
|
061fcf |
int l = xcb_str_name_length(it.data);
|
|
|
061fcf |
if (!found && l < sizeof(fontname)) {
|
|
|
061fcf |
memcpy(fontname, xcb_str_name(it.data), l);
|
|
|
061fcf |
fontname[l] = 0;
|
|
|
061fcf |
found = 1;
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
061fcf |
#ifndef NDEBUG
|
|
|
061fcf |
char buf[1024] = {};
|
|
|
061fcf |
if (l > 1023) l = 1023;
|
|
|
061fcf |
memcpy(buf, xcb_str_name(it.data), l);
|
|
|
061fcf |
buf[l] = 0;
|
|
|
061fcf |
LOGDBG("graph: init: found font: %s", buf);
|
|
|
061fcf |
#endif
|
|
|
061fcf |
|
|
|
061fcf |
xcb_str_next(&it);
|
|
|
061fcf |
}
|
|
|
061fcf |
free(r);
|
|
|
061fcf |
} else {
|
|
|
061fcf |
LOGWRN("graph: init: cannot list fonts");
|
|
|
061fcf |
}
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
63daec |
// init font
|
|
|
061fcf |
LOGDBG("graph: init: open font [%s]", fontname);
|
|
|
63daec |
g->font = xcb_generate_id(g->app->xcb);
|
|
|
061fcf |
xcb_void_cookie_t c = xcb_open_font_checked(g->app->xcb, g->font, strlen(fontname), fontname);
|
|
|
061fcf |
if (xcb_request_check(g->app->xcb, c)) {
|
|
|
061fcf |
LOGERR("graph: init: cannot open font [%s]", fontname);
|
|
|
061fcf |
xcb_change_window_attributes(g->app->xcb, g->app->win, XCB_CW_COLORMAP, &g->app->screen->default_colormap);
|
|
|
061fcf |
xcb_free_colormap(g->app->xcb, g->cm);
|
|
|
061fcf |
return 0;
|
|
|
061fcf |
}
|
|
|
63daec |
|
|
|
452870 |
// create contexts
|
|
|
63daec |
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT | XCB_GC_GRAPHICS_EXPOSURES;
|
|
|
061fcf |
uint32_t values[4] = {0, 0, g->font, 0};
|
|
|
452870 |
for(int i = 0; i < GS_COUNT; ++i) {
|
|
|
452870 |
values[0] = colors[i*2 + 1]; // foreground
|
|
|
452870 |
values[1] = colors[i*2]; // background
|
|
|
452870 |
g->gc[i] = xcb_generate_id(g->app->xcb);
|
|
|
452870 |
xcb_create_gc(g->app->xcb, g->gc[i], g->app->win, mask, values);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
return 1;
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void graphDeinit(Graph *g) {
|
|
|
452870 |
LOGDBG("graph: deinit");
|
|
|
452870 |
for(int i = 0; i < GS_COUNT; ++i)
|
|
|
452870 |
xcb_free_gc(g->app->xcb, g->gc[i]);
|
|
|
63daec |
xcb_close_font(g->app->xcb, g->font);
|
|
|
452870 |
xcb_change_window_attributes(g->app->xcb, g->app->win, XCB_CW_COLORMAP, &g->app->screen->default_colormap);
|
|
|
452870 |
xcb_free_colormap(g->app->xcb, g->cm);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void graphResize(Graph *g)
|
|
|
452870 |
{ }
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void graphDrawBackgound(Graph *g, int x, int y, int w, int h) {
|
|
|
452870 |
xcb_rectangle_t r = {x, y, w, h};
|
|
|
452870 |
xcb_poly_fill_rectangle(g->app->xcb, g->app->win, g->gc[GS_WINDOW], 1, &r);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void graphDrawButton(Graph *g, int x, int y, int w, int h, int active) {
|
|
|
452870 |
GraphStyle s = active ? GS_BUTTON_ACTIVE : GS_BUTTON_INACTIVE;
|
|
|
452870 |
xcb_rectangle_t r = {x, y, w, h};
|
|
|
452870 |
xcb_poly_fill_rectangle(g->app->xcb, g->app->win, g->gc[s], 1, &r);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
843e7a |
void textLayoutInit(TextLayout *tl, Graph *g, const char *text) {
|
|
|
452870 |
tl->g = g;
|
|
|
061fcf |
tl->x = tl->y = 0;
|
|
|
061fcf |
tl->len = 0;
|
|
|
061fcf |
|
|
|
061fcf |
// convert utf8 to char2b
|
|
|
061fcf |
const unsigned char *s = (const unsigned char *)text;
|
|
|
061fcf |
while(*s && tl->len < TL_MAXLEN) {
|
|
|
061fcf |
unsigned int d = 0xfffd;
|
|
|
061fcf |
if (!(s[0] & 0x80)) {
|
|
|
061fcf |
d = s[0];
|
|
|
061fcf |
} else
|
|
|
061fcf |
if ( (s[0] & 0xe0) == 0xc0
|
|
|
061fcf |
&& (s[1] & 0xc0) == 0x80 )
|
|
|
061fcf |
{
|
|
|
061fcf |
d = ((s[0] & 0x1f) << 6)
|
|
|
061fcf |
| ((s[1] & 0x3f) << 0);
|
|
|
061fcf |
++s;
|
|
|
061fcf |
} else
|
|
|
061fcf |
if ( (s[0] & 0xf0) == 0xe0
|
|
|
061fcf |
&& (s[1] & 0xc0) == 0x80
|
|
|
061fcf |
&& (s[2] & 0xc0) == 0x80 )
|
|
|
061fcf |
{
|
|
|
061fcf |
d = ((s[0] & 0x0f) << 12)
|
|
|
061fcf |
| ((s[1] & 0x3f) << 6)
|
|
|
061fcf |
| ((s[2] & 0x3f) << 0);
|
|
|
061fcf |
s += 2;
|
|
|
061fcf |
}
|
|
|
061fcf |
tl->text[tl->len].byte1 = d >> 8;
|
|
|
061fcf |
tl->text[tl->len].byte2 = d & 0xff;
|
|
|
061fcf |
++tl->len;
|
|
|
061fcf |
++s;
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
061fcf |
if (!tl->len)
|
|
|
061fcf |
return;
|
|
|
061fcf |
|
|
|
061fcf |
// measure text
|
|
|
061fcf |
xcb_query_text_extents_cookie_t cookie =
|
|
|
061fcf |
xcb_query_text_extents(tl->g->app->xcb, tl->g->font, tl->len, tl->text);
|
|
|
061fcf |
xcb_query_text_extents_reply_t *tx = xcb_query_text_extents_reply(tl->g->app->xcb, cookie, NULL);
|
|
|
061fcf |
if (!tx) {
|
|
|
061fcf |
LOGWRN("text layout: cannot get text extents for string [%s] len=%d", text, tl->len);
|
|
|
061fcf |
//tl->len = 0;
|
|
|
061fcf |
return;
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
061fcf |
tl->x = -tx->overall_left - tx->overall_width/2;
|
|
|
061fcf |
tl->y = tx->font_ascent/2;
|
|
|
061fcf |
free(tx);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
061fcf |
|
|
|
452870 |
void textLayoutDeinit(TextLayout *tl)
|
|
|
452870 |
{ }
|
|
|
452870 |
|
|
|
061fcf |
|
|
|
061fcf |
void textLayoutDraw(TextLayout *tl, int x, int y, int active) {
|
|
|
061fcf |
if (!tl->len) return;
|
|
|
061fcf |
GraphStyle s = active ? GS_TEXT_ACTIVE : GS_TEXT_INACTIVE;
|
|
|
061fcf |
xcb_image_text_16(tl->g->app->xcb, tl->len, tl->g->app->win, tl->g->gc[s], x + tl->x, y + tl->y, tl->text);
|
|
|
061fcf |
}
|
|
|
061fcf |
|