#include "theme.h" #include "../util.h" #include "../util/region.h" #include "../backend.h" #include "../concurrent/msgq.h" #include "../concurrent/msg.h" #include static const char* default_font_path(struct rgn* rgn) { (void) rgn; return "/usr/share/fonts/liberation/LiberationSans-Regular.ttf"; } /* ----------------------------------------------------------------------------- * Theme builder functions * -------------------------------------------------------------------------- */ struct ax_theme_builder* ax__theme_builder_new(struct rgn* rgn) { struct ax_theme_builder* thmb = ralloc_typed(rgn, struct ax_theme_builder, 1); thmb->rgn = rgn; thmb->err = NULL; thmb->dflt_font_path = NULL; thmb->color[AX_COLOR_BACKGROUND] = 0xffffff; thmb->color[AX_COLOR_SURFACE] = 0xffffff; thmb->color[AX_COLOR_PRIMARY] = 0xff0000; thmb->color[AX_COLOR_PRIMARY_ALT] = 0xff4444; thmb->color[AX_COLOR_SECONDARY] = 0x0000ff; thmb->color[AX_COLOR_SECONDARY_ALT] = 0x4444ff; thmb->color[AX_COLOR_ON_BACKGROUND] = thmb->color[AX_COLOR_ON_SURFACE] = thmb->color[AX_COLOR_ON_PRIMARY] = thmb->color[AX_COLOR_ON_SECONDARY] = 0x000000; thmb->font_size[AX_FONT_H1] = 96; thmb->font_size[AX_FONT_H2] = 60; thmb->font_size[AX_FONT_H3] = 34; thmb->font_size[AX_FONT_H4] = 24; thmb->font_size[AX_FONT_BODY] = 16; thmb->font_size[AX_FONT_BUTTON] = 14; for (size_t i = 0; i < AX_FONT__COUNT; i++) { thmb->font_path[i] = NULL; } return thmb; } void ax__theme_set_color( struct ax_theme_builder* thmb, enum ax_color_cat cat, int64_t val) { thmb->color[cat] = val; } void ax__theme_set_font( struct ax_theme_builder* thmb, enum ax_font_cat cat, const char* path, size_t size) { const char** out_path; if (cat == AX_FONT__DEFAULT) { out_path = &thmb->dflt_font_path; } else { ASSERT(cat < AX_FONT__COUNT, "invalid font category"); thmb->font_size[cat] = size; out_path = &thmb->font_path[cat]; } if (path == NULL) { *out_path = NULL; } else { *out_path = rstrdup(thmb->rgn, path); } } struct ax_theme* ax__theme_builder_finish( struct ax_theme_builder* thmb, struct rgn* dst_rgn, struct msgq* req_to_load_mq) { struct ax_theme* thm = ralloc_typed(dst_rgn, struct ax_theme, 1); if (thmb->err != NULL) { thm->err = rstrdup(dst_rgn, thmb->err); } const char* dflt_font_path = (thmb->dflt_font_path == NULL) ? default_font_path(dst_rgn) : rstrdup(dst_rgn, thmb->dflt_font_path); for (size_t i = 0; i < AX_FONT__COUNT; i++) { thm->color[i] = thmb->color[i]; thm->font_size[i] = thmb->font_size[i]; thm->font_path[i] = (thm->font_path[i] == NULL) ? dflt_font_path : rstrdup(dst_rgn, thm->font_path[i]); thm->font_handle[i] = NULL; } thm->on_load_rgn = rgn_new(dst_rgn, SMALL); thm->on_load = NULL; pthread_mutex_init(&thm->mx, NULL); rgn_pin(dst_rgn, thm, (void*) pthread_mutex_destroy); for (size_t i = 0; i < AX_FONT__COUNT; i++) { struct ax_msg_load_font* m = msgq_begin_send_typed(req_to_load_mq, ax_msg_load_font); m->theme = thm; m->category = i; msgq_end_send(req_to_load_mq); } return thm; } /* ----------------------------------------------------------------------------- * Theme functions * -------------------------------------------------------------------------- */ static inline bool is_loaded(struct ax_theme* thm) { for (size_t i = 0; i < AX_FONT__COUNT; i++) { if (thm->font_handle[i] == NULL) { return false; } } return true; } static inline void msgq_send_theme_loaded(struct msgq* mq, struct ax_theme* thm) { msgq_begin_send_typed(mq, ax_msg_theme_loaded) ->theme = thm; msgq_end_send(mq); } struct ax_font_h* ax__theme_font_handle( struct ax_theme* thm, enum ax_font_cat i) { pthread_mutex_lock(&thm->mx); struct ax_font_h* h = thm->font_handle[i]; pthread_mutex_unlock(&thm->mx); return h; } bool ax__theme_is_loaded(struct ax_theme* thm) { pthread_mutex_lock(&thm->mx); bool l = is_loaded(thm); pthread_mutex_unlock(&thm->mx); return l; } void ax__theme_set_font_handle( struct ax_theme* thm, enum ax_font_cat i, struct ax_font_h* h) { pthread_mutex_lock(&thm->mx); thm->font_handle[i] = h; if (is_loaded(thm)) { while (thm->on_load != NULL) { msgq_send_theme_loaded(thm->on_load->mq, thm); thm->on_load = thm->on_load->next; } } pthread_mutex_unlock(&thm->mx); } void ax__theme_on_load(struct ax_theme* thm, struct msgq* res_mq) { pthread_mutex_lock(&thm->mx); if (is_loaded(thm)) { msgq_send_theme_loaded(res_mq, thm); } else { struct msgq_list* l = ralloc_typed(thm->on_load_rgn, struct msgq_list, 1); l->mq = res_mq; l->next = thm->on_load; thm->on_load = l; } pthread_mutex_unlock(&thm->mx); } int ax__string_to_color_cat(const char* str, enum ax_color_cat* out_cat) { enum ax_color_cat val; #include "../../_build/color.parser.inc" if (out_cat != NULL) { *out_cat = val; } return 0; } int ax__string_to_font_cat(const char* str, enum ax_font_cat* out_cat) { enum ax_font_cat val; #include "../../_build/font.parser.inc" if (out_cat != NULL) { *out_cat = val; } return 0; } /* void ax__debug_theme(struct ax_theme* thm) { printf("=========\nTHEME INFO:\n"); for (size_t i = 0; i < AX_COLOR__COUNT; i++) { enum ax_color_cat val = i; const char* str; #include "../../_build/color.printer.inc" printf(" color `%s': #%06" PRIx64 "\n", str, thm->color[i]); } printf("--------\n"); for (size_t i = 0; i < AX_FONT__COUNT; i++) { enum ax_font_cat val = i; const char* str; #include "../../_build/font.printer.inc" printf(" font `%s': \"%s\", size %zu\n", str, thm->font_path[i], thm->font_size[i]); } } */