Skip to content

Support loading resources at runtime through callback #10970

@ubruhin

Description

@ubruhin

Feature Description

I'm a bit surprised I could not find an issue about this yet, so here I'm creating it:

Currently (for a C++ application) basically we have two options for resource loading (images, fonts):

  • as-absolute-path: Loaded at runtime by Slint, with absolute path
  • embed-files: Embedded into the application

Where as-absolute-path is a no-go as it will not work when deploying the application to another computer. So embed-files is the only real option. But this also comes with problems:

  • Bloats the compilation and the application binary
  • No advanced control over embedding, e.g. using compression (to allow developers to choose between file size vs. speed)
  • Does not allow the rest of the application to access the same resources, forcing the developers to bundle the same files multiple times in the same application
  • Does not allow to deploy the resources as files (e.g. in /usr/local/share/librepcb/myfont.ttf)

Let me explain it from the LibrePCB point of view:

  • The TTF fonts used in the Slint UI are also used for other parts of the application, in particular for QGraphicsScene and various Qt dialogs/widgets. We already have a proven setup/worflow for deploying the TTF fonts and loading them at runtime, but we can't reuse this for Slint as the fonts are getting embedded.
  • The same also applies to images, which are used by both the Slint UI and other parts of the application (e.g. Qt widgets and some parts of the backend). For this, we use Qt's resource system, so we have already bundled those images in our application. But we can't make Slint using those images, so we have to bundle them twice.

What I really miss is the ability to not bundle any files by Slint, but to load them at runtime through a callback which we can register. Slint should not care about where those files are coming from - in our case, TTF fonts would come from the file system, but images would come from the bundled Qt resources.

I am thinking about something like setting DEFAULT_SLINT_EMBED_RESOURCES=from-user-callback, and some setters like slint::set_load_image_callback(...) and slint::set_load_font_callback(). The callbacks would get a file path relative to appwindow.slint and return a binary blob (Vec<u8> or whatever).

One could argue it would be cleaner to provide only a single callback for any kind of resource. But honestly that would make our live a bit hard as we would have to parse the passed file path to determine where it needs to be loaded from (fonts from file system, images from Qt resources). But in worst case, I think that would be possible (still better than the current solution).

Actually I even wonder whether it's good to have only one DEFAULT_SLINT_EMBED_RESOURCES for any kind of resources, or whether it would be worth to control embedding separately for every kind of resource. I could imagine for example that it might be desired to load fonts at runtime, but let Slint embed images.

Curious what you think about this.

Product Impact

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:language-c++C++ API, codegen, CMake build system (mS,mO)a:language-rustRust API and codegen (mO,mS)apiChanges or additions to APIsrfcRequest for comments: proposals for changes

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions