SVG icons do not render on Windows

I have a GTK4 app and install GTK4 on Windows 10 using gvsbuild (tried versions 4.12.1, 4.12.3 and 4.12.3) as well as install librsvg.

Yet SVG icons do not render, more specifically image-missing is rendered instead of all of them.

PNG icons render fine on Windows, SVG icons render fine on Ubuntu too, but something is off on Windows.
I even tried another Rust and GTK4-based app with the same result.

There are no warnings or errors related to this in logs, gdk-pixbuf-thumbnailer.exe successfully converts SVGs into PNGs, so that part should work in GTK as well.

I spent two days debugging this with the help of folks from matrix chat and learned a few things, but in the end it doesn’t seem to work.

I’d appreciate some pointers as to how to discover why I get image-missing instead of the actual icon and maybe there is something to fix upstream or downstream about this issue. Right now I’m out of options to try.

Initially reported at SVG icons do not render on Windows (#6295) · Issues · GNOME / gtk · GitLab, but maintainers do not believe this is a bug :confused:

1 Like

Hello @nazar-pc! SVG images are working fine here! I’m using GTK4 from MSYS2

Here are a few things you may try:

  1. Check if you have lib\gdk-pixbuf-2.0\2.10.0\loaders\libpixbuf-loader-svg.dll
  2. Open lib\gdk-pixbuf-2.0\2.10.0\loaders.cache in a text editor and check if it contains an entry for svg
  3. Try running your app with a debug build of GTK and set the environment variable GTK_DEBUG=icontheme
  4. Download the sample UI file for GTK4 and remove the -1.pdf part from the name (sorry - I couldn’t upload the file here with the original name). Open the file in a text editor and set a valid path to an SVG file, then run gtk4-builder-tool preview gtk4-check-svg.ui

What do you mean by “using GTK4 from MSYS2”? I’m using GTK4 without any MSYS2 explicitly, application is built with MSVC toolchain.

It exists

It does

It does find the icon I’m interested in, when I call icon_theme.has_icon() in the app is also returns true.

One confusing thing in that output though is that is says:

Current icon themes hicolor

Even though inspector disagrees and sees no icon theme whatsoever.

It renders fine that way.

1 Like

Ok, is it a custom icon of your app or an icon from the theme (Adwaita, Numix, etc.)? What’s the path of the icon?

It is a custom icon loaded from resource. There is no icon theme whatsoever.
Icon is in the generated resources.gresource embedded into the binary itself, it is not loaded from the file system directly like in the example of .ui file.

Since PNG icon from the same resources.gresource renders fine and .has_icon() returns true, I made a conclusion something must be off in GTK itself, but the issue was closed, so here I am.

When embedding icons inside the GResource, are you using the same structure as expected by an icon theme? See the tutorial for how it works.

The whole asset loading by name is strongly tied to icon themes, and Windows doesn’t typically have fallbacks in place like, say, Ubuntu might have.

To the best of my knowledge - yes.
Example file:

<?xml version="1.0" encoding="UTF-8"?>
    <gresource prefix="/com/app/icons/scalable/actions">

Then this in Rust to actually register it:

let display = gdk::Display::default().unwrap();
let theme = gtk::IconTheme::for_display(&display);

In above example about loads fine, but about-icon doesn’t.

Custom icons are considered part of the Hicolor icon theme. I wonder if the issue stems from the lack of an index.theme file as in [MSVC] Icons from scalable/apps/ and symbolic/apps/ aren't resolved on Windows (#5303) · Issues · GNOME / gtk · GitLab

You may try creating a share\icons directory with a sample index.theme file. Best would be to copy the entire share\icons directory as generated by gvsbuild. It’s not clear to me why PNGs load but not SVGs, though

If you can provide a bundle of the app I’ll be happy to search for a fix :slight_smile:

I tried copying themes, the only thing that worked is to create share/icons on the same level as application binary, but despite the fact that there is both Adwaita and hicolor in there in my case (installed both with gvsbuild for testing purposes), inspector only sees Adwaita and icons do not render anyway.

I’d really appreciate that!

Releases · nazar-pc/space-acres · GitHub has an MSI release built and everything is built by CI, so should be reproducible if you follow instructions there (can modify CI to upload executable and trigger release workflow from a branch to collect desired build artifacts). But I need to warn you if you want to compile from source that it takes a while :slightly_smiling_face:

1 Like

Hey folks, anything else I can try to get SVG icons rendered on Windows? I can’t believe this is so hard :confused:

Sorry for the delay, I’ve been out for a few days! I’ll try investigate on this issue this weekend.

One thing I noticed is that space-acres lacks the rsvg DLL and gdk-pixbuf loader DLLs. Did you manage to build all the loaders statically into gdk-pixbuf?

gdk-pixbuf is present, while rsvg is indeed missing in the releases built in the repo, but I did have it installed locally on testing machine and it still had issues. Once I fix it there I’ll update CI to build MSI package with rsvg in it.

Interesting, tried to copy files to Windows 11 installation in a VM, the app is in bin/space-acres.exe, when I copied gdk-pixbuf-2.0 into lib (same level as bin), icons suddenly started to render :thinking:

I guess the issue is solved by copying files into correct locations, though I’m still wondering why it didn’t local with GTK installation by gvsbuild :thinking:

1 Like

Is everything fixed or do you still have issues when using gvsbuild bundles?

When application is under bin and there is lib with mentioned stuff it does work. But with GTK4 installed through gvsbuild and after simple cargo run it still doesn’t render SVGs. I even tried copying files manually, looks like main executable needs to be under bin or else it doesn’t find SVG loader for some reason.

Right. When the exe is not in a bin directory, most probably you can put a lib directory at the same level as the exe. For example, say you have a bundle directory containing app.exe:


You can place lib\gdk-pixbuf-2.0\loaders there:


That should work

It didn’t for me, this did:


I do not know why, but when bin is called differently (debug or release for Rust apps), it was not able to find loaders.
For example by default app is compiled to


I then tried both of these and none of them worked:


So for users the issue is fixed, but dev experience is bad. Not to say it should “just work” without me moving files manually in the first place. Thankfully I don’t use Windows for anything except testing, so it is how a huge issue for me personally, but something somewhere still seems a bit broken.

1 Like

Yes, that’s an issue and should be fixed! :+1:

Relevant code is at gdk-pixbuf/gdk-pixbuf-io.c · dda3da18 · GNOME / gdk-pixbuf · GitLab, but it looks OK to me: gdk_pixbuf_get_toplevel() calls g_win32_get_package_installation_directory_of_module() which should return the folder of the exe (or its parent if in a bin directory)

Could it be that gvsbuild is not enabling the relocatable option? meson_options.txt · master · GNOME / gdk-pixbuf · GitLab. Perhaps it should be enabled by default on Windows and macOS

EDIT: nope, it’s always enabled: · master · GNOME / gdk-pixbuf · GitLab

Can you check what’s returned by g_win32_get_package_installation_directory_of_module() (it’s part of GLib) by calling it in your app? I wonder if it’s a case of g_win32_get_package_installation_directory_of_module() incorrectly handles bin and lib folders (#955) · Issues · GNOME / GLib · GitLab