From 568de329efc451763a7938d81e5a1ad75ff3c51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Sat, 26 Dec 2020 02:37:29 +0100 Subject: [PATCH] Move X11 font stuff to display-x11 --- src/display-output.hh | 8 ++ src/display-x11.cc | 220 ++++++++++++++++++++++++++++++++++++++++-- src/display-x11.hh | 7 ++ src/fonts.cc | 171 ++------------------------------ src/fonts.h | 19 +--- 5 files changed, 236 insertions(+), 189 deletions(-) diff --git a/src/display-output.hh b/src/display-output.hh index 29bbc4af..e484b49e 100644 --- a/src/display-output.hh +++ b/src/display-output.hh @@ -108,6 +108,14 @@ class display_output_base { virtual void begin_draw_stuff() {} virtual void end_draw_stuff() {} virtual void clear_text(int exposures) {} + + // font stuff + virtual int font_height(int) { return 0; } + virtual int font_ascent(int) { return 0; } + virtual int font_descent(int) { return 0; } + virtual void setup_fonts(void) {} + virtual void set_font(int) {} + virtual void free_fonts(bool utf8) {} virtual void load_fonts(bool utf8) {} // tty interface diff --git a/src/display-x11.cc b/src/display-x11.cc index 820a6f92..196f66db 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -76,6 +76,57 @@ extern long current_color; static int xft_dpi = -1; #endif /* BUILD_XFT */ +/* for x_fonts */ +struct x_font_list { + XFontStruct *font; + XFontSet fontset; + +#ifdef BUILD_XFT + XftFont *xftfont; + int font_alpha; +#endif + + x_font_list() + : font(nullptr), + fontset(nullptr) +#ifdef BUILD_XFT + , + xftfont(nullptr), + font_alpha(0xffff) +#endif + { + } +}; + +static std::vector x_fonts; /* indexed by selected_font */ + +#ifdef BUILD_XFT +namespace { +class xftalpha_setting : public conky::simple_config_setting { + using Base = conky::simple_config_setting; + + protected: + void lua_setter(lua::state &l, bool init) override { + lua::stack_sentry s(l, -2); + + Base::lua_setter(l, init); + + if (init && out_to_x.get(*state)) { + x_fonts.resize(std::max(1, static_cast(fonts.size()))); + x_fonts[0].font_alpha = do_convert(l, -1).first * 0xffff; + } + + ++s; + } + + public: + xftalpha_setting() : Base("xftalpha", 1.0, false) {} +}; + +xftalpha_setting xftalpha; +} // namespace +#endif /* BUILD_XFT */ + static void X11_create_window(); struct _x11_stuff_s { @@ -538,17 +589,17 @@ int display_output_x11::calc_text_width(const char *s) { XGlyphInfo gi; if (utf8_mode.get(*state)) { - XftTextExtentsUtf8(display, fonts[selected_font].xftfont, + XftTextExtentsUtf8(display, x_fonts[selected_font].xftfont, reinterpret_cast(s), slen, &gi); } else { - XftTextExtents8(display, fonts[selected_font].xftfont, + XftTextExtents8(display, x_fonts[selected_font].xftfont, reinterpret_cast(s), slen, &gi); } return gi.xOff; } #endif /* BUILD_XFT */ - return XTextWidth(fonts[selected_font].font, s, slen); + return XTextWidth(x_fonts[selected_font].font, s, slen); } void display_output_x11::draw_string_at(int x, int y, const char *s, int w) { @@ -565,19 +616,19 @@ void display_output_x11::draw_string_at(int x, int y, const char *s, int w) { c2.color.red = c.red; c2.color.green = c.green; c2.color.blue = c.blue; - c2.color.alpha = fonts[selected_font].font_alpha; + c2.color.alpha = x_fonts[selected_font].font_alpha; if (utf8_mode.get(*state)) { - XftDrawStringUtf8(window.xftdraw, &c2, fonts[selected_font].xftfont, x, y, - reinterpret_cast(s), w); + XftDrawStringUtf8(window.xftdraw, &c2, x_fonts[selected_font].xftfont, x, + y, reinterpret_cast(s), w); } else { - XftDrawString8(window.xftdraw, &c2, fonts[selected_font].xftfont, x, y, + XftDrawString8(window.xftdraw, &c2, x_fonts[selected_font].xftfont, x, y, reinterpret_cast(s), w); } } else #endif { if (utf8_mode.get(*state)) { - Xutf8DrawString(display, window.drawable, fonts[selected_font].fontset, + Xutf8DrawString(display, window.drawable, x_fonts[selected_font].fontset, window.gc, x, y, s, w); } else { XDrawString(display, window.drawable, window.gc, x, y, s, w); @@ -656,7 +707,158 @@ void display_output_x11::clear_text(int exposures) { } } -void display_output_x11::load_fonts(bool utf8) { ::load_fonts(utf8); } +#ifdef BUILD_XFT + +int display_output_x11::font_height(int f) { + assert(f < x_fonts.size()); + if (use_xft.get(*state)) { + return x_fonts[f].xftfont->ascent + x_fonts[f].xftfont->descent; + } else { + return x_fonts[f].font->max_bounds.ascent + + x_fonts[f].font->max_bounds.descent; + } +} + +int display_output_x11::font_ascent(int f) { + assert(f < x_fonts.size()); + if (use_xft.get(*state)) { + return x_fonts[f].xftfont->ascent; + } else { + return x_fonts[f].font->max_bounds.ascent; + } +} + +int display_output_x11::font_descent(int f) { + assert(f < x_fonts.size()); + if (use_xft.get(*state)) { + return x_fonts[f].xftfont->descent; + } else { + return x_fonts[f].font->max_bounds.descent; + } +} + +#else + +int display_output_x11::font_height(int f) { + assert(f < x_fonts.size()); + return x_fonts[f].font->max_bounds.ascent + + x_fonts[f].font->max_bounds.descent; +} + +int display_output_x11::font_ascent(int f) { + assert(f < x_fonts.size()); + return x_fonts[f].font->max_bounds.ascent; +} + +int display_output_x11::font_descent(int f) { + assert(f < x_fonts.size()); + return x_fonts[f].font->max_bounds.descent; +} + +#endif + +void display_output_x11::setup_fonts(void) { +#ifdef BUILD_XFT + if (use_xft.get(*state)) { + if (window.xftdraw != nullptr) { + XftDrawDestroy(window.xftdraw); + window.xftdraw = nullptr; + } + window.xftdraw = XftDrawCreate(display, window.drawable, window.visual, + window.colourmap); + } +#endif /* BUILD_XFT */ +} + +void display_output_x11::set_font(int f) { +#ifdef BUILD_XFT + if (use_xft.get(*state)) { return; } +#endif /* BUILD_XFT */ + if (x_fonts.size() > f && x_fonts[f].font != nullptr && + window.gc != nullptr) { + XSetFont(display, window.gc, x_fonts[f].font->fid); + } +} + +void display_output_x11::free_fonts(bool utf8) { + for (auto &font : x_fonts) { +#ifdef BUILD_XFT + if (use_xft.get(*state)) { + /* + * Do we not need to close fonts with Xft? Unsure. Not freeing the + * fonts seems to incur a slight memory leak, but it also prevents + * a crash. + * + * XftFontClose(display, x_fonts[i].xftfont); + */ + } else +#endif /* BUILD_XFT */ + { + if (font.font != nullptr) { XFreeFont(display, font.font); } + if (utf8 && (font.fontset != nullptr)) { + XFreeFontSet(display, font.fontset); + } + } + } + x_fonts.clear(); +#ifdef BUILD_XFT + if (window.xftdraw != nullptr) { + XftDrawDestroy(window.xftdraw); + window.xftdraw = nullptr; + } +#endif /* BUILD_XFT */ +} +void display_output_x11::load_fonts(bool utf8) { + x_fonts.resize(fonts.size()); + for (int i = 0; i < fonts.size(); i++) { + auto &font = fonts[i]; + auto &xfont = x_fonts[i]; +#ifdef BUILD_XFT + /* load Xft font */ + if (use_xft.get(*state)) { + if (xfont.xftfont == nullptr) { + xfont.xftfont = XftFontOpenName(display, screen, font.name.c_str()); + } + + if (xfont.xftfont != nullptr) { continue; } + + NORM_ERR("can't load Xft font '%s'", font.name.c_str()); + if ((xfont.xftfont = XftFontOpenName(display, screen, "courier-12")) != + nullptr) { + continue; + } + + CRIT_ERR(nullptr, nullptr, "can't load Xft font '%s'", "courier-12"); + + continue; + } +#endif + if (utf8 && xfont.fontset == nullptr) { + char **missing; + int missingnum; + char *missingdrawn; + xfont.fontset = XCreateFontSet(display, font.name.c_str(), &missing, + &missingnum, &missingdrawn); + XFreeStringList(missing); + if (xfont.fontset == nullptr) { + NORM_ERR("can't load font '%s'", font.name.c_str()); + xfont.fontset = XCreateFontSet(display, "fixed", &missing, &missingnum, + &missingdrawn); + if (xfont.fontset == nullptr) { + CRIT_ERR(nullptr, nullptr, "can't load font '%s'", "fixed"); + } + } + } + /* load normal font */ + if ((xfont.font == nullptr) && + (xfont.font = XLoadQueryFont(display, font.name.c_str())) == nullptr) { + NORM_ERR("can't load font '%s'", font.name.c_str()); + if ((xfont.font = XLoadQueryFont(display, "fixed")) == nullptr) { + CRIT_ERR(nullptr, nullptr, "can't load font '%s'", "fixed"); + } + } + } +} #endif /* BUILD_X11 */ diff --git a/src/display-x11.hh b/src/display-x11.hh index e1cb20f2..09c0789a 100644 --- a/src/display-x11.hh +++ b/src/display-x11.hh @@ -71,6 +71,13 @@ class display_output_x11 : public display_output_base { virtual void end_draw_stuff(); virtual void clear_text(int exposures); + + virtual int font_height(int); + virtual int font_ascent(int); + virtual int font_descent(int); + virtual void setup_fonts(void); + virtual void set_font(int); + virtual void free_fonts(bool utf8); virtual void load_fonts(bool utf8); // X11-specific diff --git a/src/fonts.cc b/src/fonts.cc index 31c84a64..87f23d06 100644 --- a/src/fonts.cc +++ b/src/fonts.cc @@ -28,6 +28,7 @@ */ #include "fonts.h" +#include "display-output.hh" #include "logging.h" unsigned int selected_font = 0; @@ -53,55 +54,14 @@ conky::simple_config_setting font_template[10] = { {"font0", ""}, {"font1", ""}, {"font2", ""}, {"font3", ""}, {"font4", ""}, {"font5", ""}, {"font6", ""}, {"font7", ""}, {"font8", ""}, {"font9", ""}}; -#ifdef BUILD_XFT -namespace { -class xftalpha_setting : public conky::simple_config_setting { - using Base = conky::simple_config_setting; - - protected: - void lua_setter(lua::state &l, bool init) override { - lua::stack_sentry s(l, -2); - - Base::lua_setter(l, init); - - if (init && out_to_x.get(*state)) { - fonts[0].font_alpha = do_convert(l, -1).first * 0xffff; - } - - ++s; - } - - public: - xftalpha_setting() : Base("xftalpha", 1.0, false) {} -}; - -xftalpha_setting xftalpha; -} // namespace -#endif /* BUILD_XFT */ - void set_font() { -#ifdef BUILD_XFT - if (use_xft.get(*state)) { return; } -#endif /* BUILD_XFT */ - if (fonts.size() > selected_font && fonts[selected_font].font != nullptr && - window.gc != nullptr) { - XSetFont(display, window.gc, fonts[selected_font].font->fid); - } + if (selected_font >= fonts.size()) return; + for (auto output : display_outputs()) output->set_font(selected_font); } void setup_fonts() { DBGP2("setting up fonts"); - if (!out_to_x.get(*state)) { return; } -#ifdef BUILD_XFT - if (use_xft.get(*state)) { - if (window.xftdraw != nullptr) { - XftDrawDestroy(window.xftdraw); - window.xftdraw = nullptr; - } - window.xftdraw = XftDrawCreate(display, window.drawable, window.visual, - window.colourmap); - } -#endif /* BUILD_XFT */ + for (auto output : display_outputs()) output->setup_fonts(); set_font(); } @@ -114,140 +74,27 @@ int add_font(const char *data_in) { } void free_fonts(bool utf8) { - if (!out_to_x.get(*state)) { return; } - for (auto &font : fonts) { -#ifdef BUILD_XFT - if (use_xft.get(*state)) { - /* - * Do we not need to close fonts with Xft? Unsure. Not freeing the - * fonts seems to incur a slight memory leak, but it also prevents - * a crash. - * - * XftFontClose(display, fonts[i].xftfont); - */ - } else -#endif /* BUILD_XFT */ - { - if (font.font != nullptr) { XFreeFont(display, font.font); } - if (utf8 && (font.fontset != nullptr)) { - XFreeFontSet(display, font.fontset); - } - } - } + for (auto output : display_outputs()) output->free_fonts(utf8); fonts.clear(); selected_font = 0; -#ifdef BUILD_XFT - if (window.xftdraw != nullptr) { - XftDrawDestroy(window.xftdraw); - window.xftdraw = nullptr; - } -#endif /* BUILD_XFT */ } void load_fonts(bool utf8) { DBGP2("loading fonts"); - if (!out_to_x.get(*state)) { return; } - for (auto &font : fonts) { -#ifdef BUILD_XFT - /* load Xft font */ - if (use_xft.get(*state)) { - if (font.xftfont == nullptr) { - font.xftfont = XftFontOpenName(display, screen, font.name.c_str()); - } - - if (font.xftfont != nullptr) { continue; } - - NORM_ERR("can't load Xft font '%s'", font.name.c_str()); - if ((font.xftfont = XftFontOpenName(display, screen, "courier-12")) != - nullptr) { - continue; - } - - CRIT_ERR(nullptr, nullptr, "can't load Xft font '%s'", "courier-12"); - - continue; - } -#endif - if (utf8 && font.fontset == nullptr) { - char **missing; - int missingnum; - char *missingdrawn; - font.fontset = XCreateFontSet(display, font.name.c_str(), &missing, - &missingnum, &missingdrawn); - XFreeStringList(missing); - if (font.fontset == nullptr) { - NORM_ERR("can't load font '%s'", font.name.c_str()); - font.fontset = XCreateFontSet(display, "fixed", &missing, &missingnum, - &missingdrawn); - if (font.fontset == nullptr) { - CRIT_ERR(nullptr, nullptr, "can't load font '%s'", "fixed"); - } - } - } - /* load normal font */ - if ((font.font == nullptr) && - (font.font = XLoadQueryFont(display, font.name.c_str())) == nullptr) { - NORM_ERR("can't load font '%s'", font.name.c_str()); - if ((font.font = XLoadQueryFont(display, "fixed")) == nullptr) { - CRIT_ERR(nullptr, nullptr, "can't load font '%s'", "fixed"); - } - } - } + for (auto output : display_outputs()) output->load_fonts(utf8); } -#ifdef BUILD_XFT - int font_height() { - if (!out_to_x.get(*state)) { return 0; } assert(selected_font < fonts.size()); - if (use_xft.get(*state)) { - return fonts[selected_font].xftfont->ascent + - fonts[selected_font].xftfont->descent; - } else { - return fonts[selected_font].font->max_bounds.ascent + - fonts[selected_font].font->max_bounds.descent; - } + return display_output()->font_height(selected_font); } int font_ascent() { - if (!out_to_x.get(*state)) { return 0; } assert(selected_font < fonts.size()); - if (use_xft.get(*state)) { - return fonts[selected_font].xftfont->ascent; - } else { - return fonts[selected_font].font->max_bounds.ascent; - } + return display_output()->font_ascent(selected_font); } int font_descent() { - if (!out_to_x.get(*state)) { return 0; } assert(selected_font < fonts.size()); - if (use_xft.get(*state)) { - return fonts[selected_font].xftfont->descent; - } else { - return fonts[selected_font].font->max_bounds.descent; - } + return display_output()->font_descent(selected_font); } - -#else - -int font_height() { - if (!out_to_x.get(*state)) { return 0; } - assert(selected_font < fonts.size()); - return fonts[selected_font].font->max_bounds.ascent + - fonts[selected_font].font->max_bounds.descent; -} - -int font_ascent() { - if (!out_to_x.get(*state)) { return 0; } - assert(selected_font < fonts.size()); - return fonts[selected_font].font->max_bounds.ascent; -} - -int font_descent() { - if (!out_to_x.get(*state)) { return 0; } - assert(selected_font < fonts.size()); - return fonts[selected_font].font->max_bounds.descent; -} - -#endif diff --git a/src/fonts.h b/src/fonts.h index bcbf4f43..6f8a8c5c 100644 --- a/src/fonts.h +++ b/src/fonts.h @@ -37,25 +37,8 @@ /* for fonts */ struct font_list { std::string name; - XFontStruct *font; - XFontSet fontset; -#ifdef BUILD_XFT - XftFont *xftfont; - int font_alpha; -#endif - - font_list() - : name(), - font(nullptr), - fontset(nullptr) -#ifdef BUILD_XFT - , - xftfont(nullptr), - font_alpha(0xffff) -#endif - { - } + font_list() : name() {} }; /* direct access to registered fonts (FIXME: bad encapsulation) */