menu view: respond to font configuration changes

Issue #3875
This commit is contained in:
Norman Feske 2020-09-07 15:57:06 +02:00 committed by Christian Helmuth
parent 4aca94b08b
commit c05f716478
3 changed files with 137 additions and 11 deletions

View File

@ -72,6 +72,71 @@ install_config {
</route> </route>
</start> </start>
<start name="fonts_fs_config_rom">
<resource name="RAM" quantum="4M"/>
<binary name="dynamic_rom"/>
<provides> <service name="ROM"/> </provides>
<config verbose="yes">
<rom name="config">
<inline description="small">
<config>
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>
<dir name="fonts">
<dir name="title">
<ttf name="regular" path="/Vera.ttf" size_px="18" cache="256K"/>
</dir>
<dir name="text">
<ttf name="regular" path="/Vera.ttf" size_px="14" cache="256K"/>
</dir>
<dir name="annotation">
<ttf name="regular" path="/Vera.ttf" size_px="11" cache="256K"/>
</dir>
<dir name="monospace">
<ttf name="regular" path="/VeraMono.ttf" size_px="14" cache="256K"/>
</dir>
</dir>
</vfs>
<default-policy root="/fonts" />
</config>
</inline>
<sleep milliseconds="1000" />
<inline description="big">
<config>
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>
<dir name="fonts">
<dir name="title">
<ttf name="regular" path="/Vera.ttf" size_px="28" cache="256K"/>
</dir>
<dir name="text">
<ttf name="regular" path="/Vera.ttf" size_px="24" cache="256K"/>
</dir>
<dir name="annotation">
<ttf name="regular" path="/Vera.ttf" size_px="21" cache="256K"/>
</dir>
<dir name="monospace">
<ttf name="regular" path="/VeraMono.ttf" size_px="24" cache="256K"/>
</dir>
</dir>
</vfs>
<default-policy root="/fonts" />
</config>
</inline>
<sleep milliseconds="1000" />
</rom>
</config>
</start>
<start name="dynamic_rom"> <start name="dynamic_rom">
<resource name="RAM" quantum="4M"/> <resource name="RAM" quantum="4M"/>
<provides> <service name="ROM"/> </provides> <provides> <service name="ROM"/> </provides>
@ -127,7 +192,7 @@ install_config {
</dialog> </dialog>
</inline> </inline>
<sleep milliseconds="1000" /> <sleep milliseconds="3000" />
<inline description="dependency graph"> <inline description="dependency graph">
<dialog> <dialog>
@ -156,7 +221,7 @@ install_config {
</dialog> </dialog>
</inline> </inline>
<sleep milliseconds="1000" /> <sleep milliseconds="3000" />
<inline description="example menu"> <inline description="example menu">
<dialog> <dialog>
@ -203,7 +268,7 @@ install_config {
</dialog> </dialog>
</inline> </inline>
<sleep milliseconds="1000" /> <sleep milliseconds="3000" />
<inline description="example menu"> <inline description="example menu">
<dialog> <dialog>
@ -220,7 +285,7 @@ install_config {
</dialog> </dialog>
</inline> </inline>
<sleep milliseconds="1000" /> <sleep milliseconds="3000" />
</rom> </rom>
</config> </config>
@ -236,7 +301,7 @@ install_config {
<resource name="RAM" quantum="8M"/> <resource name="RAM" quantum="8M"/>
<binary name="vfs"/> <binary name="vfs"/>
<route> <route>
<service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service> <service name="ROM" label="config"> <child name="fonts_fs_config_rom"/> </service>
<any-service> <parent/> </any-service> <any-service> <parent/> </any-service>
</route> </route>
<provides> <service name="File_system"/> </provides> <provides> <service name="File_system"/> </provides>

View File

@ -115,7 +115,8 @@ struct Menu_view::Main
Directory _fonts_dir { _root_dir, "fonts" }; Directory _fonts_dir { _root_dir, "fonts" };
Directory _styles_dir { _root_dir, "styles" }; Directory _styles_dir { _root_dir, "styles" };
Style_database _styles { _env.ram(), _env.rm(), _heap, _fonts_dir, _styles_dir }; Style_database _styles { _env.ram(), _env.rm(), _heap, _fonts_dir, _styles_dir,
_dialog_update_handler };
Animator _animator { }; Animator _animator { };
@ -223,6 +224,8 @@ void Menu_view::Main::_update_hover_report()
void Menu_view::Main::_handle_dialog_update() void Menu_view::Main::_handle_dialog_update()
{ {
_styles.flush_outdated_styles();
try { try {
Xml_node const config = _config.xml(); Xml_node const config = _config.xml();
@ -275,6 +278,9 @@ void Menu_view::Main::_handle_config()
_hover_reporter.enabled(false); _hover_reporter.enabled(false);
} }
_config.xml().with_sub_node("vfs", [&] (Xml_node const &vfs_node) {
_vfs_env.root_dir().apply_config(vfs_node); });
_handle_dialog_update(); _handle_dialog_update();
} }

View File

@ -38,10 +38,24 @@ struct Menu_view::Label_style
class Menu_view::Style_database class Menu_view::Style_database
{ {
public:
struct Changed_handler : Interface
{
virtual void handle_style_changed() = 0;
};
private: private:
enum { PATH_MAX_LEN = 200 }; enum { PATH_MAX_LEN = 200 };
/*
* True whenever the style must be updated, e.g., because the font size
* changed. The member is marked as 'mutable' because it must be
* writeable by the 'Font_entry'.
*/
bool mutable _out_of_date = false;
typedef String<PATH_MAX_LEN> Path; typedef String<PATH_MAX_LEN> Path;
typedef ::File::Reading_failed Reading_failed; typedef ::File::Reading_failed Reading_failed;
@ -108,10 +122,25 @@ class Menu_view::Style_database
{ {
Path const path; Path const path;
bool out_of_date = false;
Style_database const &_style_database;
Cached_font::Limit _font_cache_limit { 256*1024 }; Cached_font::Limit _font_cache_limit { 256*1024 };
Vfs_font _vfs_font; Vfs_font _vfs_font;
Cached_font _cached_font; Cached_font _cached_font;
Watch_handler<Font_entry> _glyphs_changed_handler;
void _handle_glyphs_changed()
{
out_of_date = true;
_style_database._out_of_date = true;
/* schedule dialog redraw */
Signal_transmitter(_style_database._style_changed_sigh).submit();
}
Text_painter::Font const &font() const { return _cached_font; } Text_painter::Font const &font() const { return _cached_font; }
/** /**
@ -119,11 +148,15 @@ class Menu_view::Style_database
* *
* \throw Reading_failed * \throw Reading_failed
*/ */
Font_entry(Directory const &fonts_dir, Path const &path, Allocator &alloc) Font_entry(Directory const &fonts_dir, Path const &path, Allocator &alloc,
Style_database const &style_database)
try : try :
path(path), path(path),
_style_database(style_database),
_vfs_font(alloc, fonts_dir, path), _vfs_font(alloc, fonts_dir, path),
_cached_font(alloc, _vfs_font, _font_cache_limit) _cached_font(alloc, _vfs_font, _font_cache_limit),
_glyphs_changed_handler(fonts_dir, Path(path, "/glyphs"),
*this, &Font_entry::_handle_glyphs_changed)
{ } { }
catch (...) { throw Reading_failed(); } catch (...) { throw Reading_failed(); }
}; };
@ -134,6 +167,8 @@ class Menu_view::Style_database
Directory const &_fonts_dir; Directory const &_fonts_dir;
Directory const &_styles_dir; Directory const &_styles_dir;
Signal_context_capability _style_changed_sigh;
/* /*
* The lists are mutable because they are populated as a side effect of * The lists are mutable because they are populated as a side effect of
* calling the const lookup functions. * calling the const lookup functions.
@ -194,10 +229,12 @@ class Menu_view::Style_database
public: public:
Style_database(Ram_allocator &ram, Region_map &rm, Allocator &alloc, Style_database(Ram_allocator &ram, Region_map &rm, Allocator &alloc,
Directory const &fonts_dir, Directory const &styles_dir) Directory const &fonts_dir, Directory const &styles_dir,
Signal_context_capability style_changed_sigh)
: :
_ram(ram), _rm(rm), _alloc(alloc), _ram(ram), _rm(rm), _alloc(alloc),
_fonts_dir(fonts_dir), _styles_dir(styles_dir) _fonts_dir(fonts_dir), _styles_dir(styles_dir),
_style_changed_sigh(style_changed_sigh)
{ } { }
Texture<Pixel_rgb888> const *texture(Xml_node node, char const *png_name) const Texture<Pixel_rgb888> const *texture(Xml_node node, char const *png_name) const
@ -236,7 +273,7 @@ class Menu_view::Style_database
*/ */
try { try {
Font_entry *e = new (_alloc) Font_entry *e = new (_alloc)
Font_entry(_fonts_dir, path, _alloc); Font_entry(_fonts_dir, path, _alloc, *this);
_fonts.insert(e); _fonts.insert(e);
return &e->font(); return &e->font();
@ -255,6 +292,24 @@ class Menu_view::Style_database
{ {
fn(_label_style(node)); fn(_label_style(node));
} }
void flush_outdated_styles()
{
if (!_out_of_date)
return;
/* flush fonts that are marked as out of date */
for (Font_entry *font = _fonts.first(), *next = nullptr; font; ) {
next = font->next();
if (font->out_of_date) {
_fonts.remove(font);
destroy(_alloc, font);
}
font = next;
}
_out_of_date = false;
}
}; };
#endif /* _STYLE_DATABASE_H_ */ #endif /* _STYLE_DATABASE_H_ */