fyne
fyne copied to clipboard
Some SVG resources don't update appearance correctly with the theme
Checklist
- [X] I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
- [X] This issue only relates to a single bug. I will open new issues for any other problems.
Describe the bug
I have some SVG resources that aren't displaying properly with the NewThemedResource wrapper. Rather than updating the fill color appropriately, it seems that the fill is becoming transparent and the SVG is not drawing at all. They draw normally without the themed resource wrapper but using the original fill color.
How to reproduce
run the example app and switch the OS theme from light to dark. observe that the Fyne app updates its theming but one button themes correctly and the other doesn't show its icon at all
Screenshots
Example code
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
var ResDiscSvg = &fyne.StaticResource{
StaticName: "disc.svg",
StaticContent: []byte(
"<svg fill=\"#000000\" version=\"1.1\" id=\"Capa_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" \r\n\t width=\"800px\" height=\"800px\" viewBox=\"0 0 547.74 547.74\"\r\n\t xml:space=\"preserve\">\r\n<g>\r\n\t<g>\r\n\t\t<path d=\"M273.87,547.74c151.256,0,273.87-122.617,273.87-273.87S425.126,0,273.87,0S0,122.617,0,273.87\r\n\t\t\tS122.614,547.74,273.87,547.74z M354.122,46.31c40.318,14.217,75.723,38.847,102.987,70.662L356.255,219.99\r\n\t\t\tc-9.939-15.166-23.954-27.421-40.487-35.208L354.122,46.31z M314.626,35.144l-11.539,143.704\r\n\t\t\tc-5.33-1.625-10.783-2.794-16.288-3.498L268.062,31.824C283.656,31.429,299.256,32.543,314.626,35.144z M273.87,228.735\r\n\t\t\tc24.927,0,45.135,20.208,45.135,45.135s-20.208,45.135-45.135,45.135s-45.135-20.208-45.135-45.135\r\n\t\t\tS248.943,228.735,273.87,228.735z M211.709,350.22c14.18,11.53,31.294,18.854,49.269,21.246l-49.177,135.519\r\n\t\t\tc-40.481-10.799-78.015-32.045-108.291-62.229L211.709,350.22z\"/>\r\n\t</g>\r\n</g>\r\n</svg>\r\n"),
}
var ResFilterSvg = &fyne.StaticResource{
StaticName: "filter.svg",
StaticContent: []byte(
"<svg fill=\"#000000\" version=\"1.1\" id=\"Capa_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" \r\n\t width=\"800px\" height=\"800px\" viewBox=\"0 0 971.986 971.986\"\r\n\t xml:space=\"preserve\">\r\n<g>\r\n\t<path d=\"M370.216,459.3c10.2,11.1,15.8,25.6,15.8,40.6v442c0,26.601,32.1,40.101,51.1,21.4l123.3-141.3\r\n\t\tc16.5-19.8,25.6-29.601,25.6-49.2V500c0-15,5.7-29.5,15.8-40.601L955.615,75.5c26.5-28.8,6.101-75.5-33.1-75.5h-873\r\n\t\tc-39.2,0-59.7,46.6-33.1,75.5L370.216,459.3z\"/>\r\n</g>\r\n</svg>\r\n"),
}
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Themed SVG bug")
discSvg := theme.NewThemedResource(ResDiscSvg)
filterSvg := theme.NewThemedResource(ResFilterSvg)
content := container.New(layout.NewFormLayout(),
widget.NewLabel("without themed wrapper"),
container.NewHBox(
widget.NewButtonWithIcon("", ResDiscSvg, nil),
widget.NewButtonWithIcon("", ResFilterSvg, nil),
),
widget.NewLabel("with themed wrapper"),
container.NewHBox(
widget.NewButtonWithIcon("", discSvg, nil),
widget.NewButtonWithIcon("", filterSvg, nil),
),
)
myWindow.SetContent(content)
myWindow.ShowAndRun()
}
Fyne version
2.3.4
Go compiler version
go1.19.4 darwin/amd64
Operating system and version
Mac OS
Additional Information
No response
I have the same bug with some SVGs (in addition to the non-correctly displayed at all SVGs...), and I noticed that svg with grayish stroke are OK, while black stroke no.
I don't know what does that mean though... Zero experience with SVG
me too
It would be helpful if you can provide more data, such as the icon you are trying to use. "Me too" doesn't help us fix the issue.
Only use theme.xxxIcon() to correspond to the theme
is code demo
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("ico.demo")
// me diy
diySvgToContent := `<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4 24C4 35.0457 12.9543 44 24 44V44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M36 24C36 17.3726 30.6274 12 24 12C17.3726 12 12 17.3726 12 24C12 30.6274 17.3726 36 24 36V36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>`
diySvgToResource := fyne.NewStaticResource("logo.svg", []byte(diySvgToContent))
// copy fyne's home.svg filepath'code to svgContentToFyne : /gopath/pkg/mod/fyne.io/fyne/[email protected]/theme/icons/home.svg
fyneSvgToContent := `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/><path d="M0 0h24v24H0z" fill="none"/></svg>`
fyneSvgToResource := fyne.NewStaticResource("home.svg", []byte(fyneSvgToContent))
//
a := widget.NewButtonWithIcon("diySvg", diySvgToResource, nil)
b := widget.NewButtonWithIcon("fyne's Icon", theme.DownloadIcon(), nil)
c := widget.NewButtonWithIcon("fyne's Svg", fyneSvgToResource, nil)
//
layouta := container.NewHBox(a, b, c)
layout := container.NewVBox(layouta)
myWindow.SetContent(layout)
myWindow.Resize(fyne.NewSize(600, 400))
myWindow.ShowAndRun()
}
I found a solution use "theme.NewThemedResource()" but only fyne's svg
c := widget.NewButtonWithIcon("fyne's Svg", theme.NewThemedResource(fyneSvgToResource), nil)
That is how it is supposed to work, with ThemedResource. It does not only work with Fyne SVGs - all icons I have tried from material design icon set work great.
这就是 ThemedResource 应该如何工作的。 它不仅适用于 Fyne SVG - 我在材料设计图标集中尝试过的所有图标都效果很好。
In other words, fyne's icon is acceptable, but user-defined icons are not. The requirement is that user-defined icons must have the same effect to solve the problem.
这就是 ThemedResource 应该如何工作的。 它不仅适用于 Fyne SVG - 我在材料设计图标集中尝试过的所有图标都效果很好。
Try how to make the icon here also successful https://iconpark.oceanengine.com/official
i found a problem stroke="#333" To "stroke="#fff"" will default to white
diySvgToContent := `<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 24C4 35.0457 12.9543 44 24 44V44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M36 24C36 17.3726 30.6274 12 24 12C17.3726 12 12 17.3726 12 24C12 30.6274 17.3726 36 24 36V36" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`
Explain that fyne's theme tool does not uniformly process the color of svg
It seems that the way to deal with custom svg colors here needs to be adjusted. User-defined svg is not in the fyne framework, which is special
// Name returns the underlying resource name (used for caching).
func (res *ThemedResource) Name() string {
prefix := res.ColorName
if prefix == "" {
prefix = "foreground_"
} else {
prefix += "_"
}
return string(prefix) + res.source.Name()
}
// Content returns the underlying content of the resource adapted to the current text color.
func (res *ThemedResource) Content() []byte {
name := res.ColorName
if name == "" {
name = ColorNameForeground
}
return svg.Colorize(res.source.Content(), safeColorLookup(name, currentVariant()))
}
In other words, fyne's icon is acceptable, but user-defined icons are not. The requirement is that user-defined icons must have the same effect to solve the problem.
No, this is incorrect and unhelpful. You will see many apps that use custom icons and they theme correctly. It has been extensively tested with the extended material design icon set.
I found 2 very similar icons from google's material icons set, one works well, the other is not even displayed
Good https://fonts.google.com/icons?selected=Material%20Icons%3Aadd_to_queue%3A
Bad https://fonts.google.com/icons?selected=Material%20Icons%3Aremove_from_queue%3A
I found 2 very similar icons from google's material icons set, one works well, the other is not even displayed
I cannot replicate with simple icon load. It seems like this relates to the themed resource code not the SVG loader.
Fixed on develop for next release
Unfortunately I have to reopen this as there are still some SVG icons which don't theme correctly. The ones in the original repro instructions were indeed fixed along with several others, but here is still a problematic one:
package main
import (
"os"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
var ResDiscSvg = &fyne.StaticResource{
StaticName: "disc.svg",
StaticContent: []byte(
"<svg fill=\"#000000\" version=\"1.1\" id=\"Capa_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" \r\n\t width=\"800px\" height=\"800px\" viewBox=\"0 0 547.74 547.74\"\r\n\t xml:space=\"preserve\">\r\n<g>\r\n\t<g>\r\n\t\t<path d=\"M273.87,547.74c151.256,0,273.87-122.617,273.87-273.87S425.126,0,273.87,0S0,122.617,0,273.87\r\n\t\t\tS122.614,547.74,273.87,547.74z M354.122,46.31c40.318,14.217,75.723,38.847,102.987,70.662L356.255,219.99\r\n\t\t\tc-9.939-15.166-23.954-27.421-40.487-35.208L354.122,46.31z M314.626,35.144l-11.539,143.704\r\n\t\t\tc-5.33-1.625-10.783-2.794-16.288-3.498L268.062,31.824C283.656,31.429,299.256,32.543,314.626,35.144z M273.87,228.735\r\n\t\t\tc24.927,0,45.135,20.208,45.135,45.135s-20.208,45.135-45.135,45.135s-45.135-20.208-45.135-45.135\r\n\t\t\tS248.943,228.735,273.87,228.735z M211.709,350.22c14.18,11.53,31.294,18.854,49.269,21.246l-49.177,135.519\r\n\t\t\tc-40.481-10.799-78.015-32.045-108.291-62.229L211.709,350.22z\"/>\r\n\t</g>\r\n</g>\r\n</svg>\r\n"),
}
var ResFilterSvg = &fyne.StaticResource{
StaticName: "filter.svg",
StaticContent: []byte(
"<?xml version=\"1.0\" encoding=\"utf-8\"?><svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 122.88 107.41\" style=\"enable-background:new 0 0 122.88 107.41\" xml:space=\"preserve\"><style type=\"text/css\">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path class=\"st0\" d=\"M60.83,17.19C68.84,8.84,74.45,1.62,86.79,0.21c23.17-2.66,44.48,21.06,32.78,44.41 c-3.33,6.65-10.11,14.56-17.61,22.32c-8.23,8.52-17.34,16.87-23.72,23.2l-17.4,17.26L46.46,93.56C29.16,76.9,0.95,55.93,0.02,29.95 C-0.63,11.75,13.73,0.09,30.25,0.3C45.01,0.5,51.22,7.84,60.83,17.19L60.83,17.19L60.83,17.19z\"/></g></svg>"),
}
func main() {
myApp := app.New()
myWindow := myApp.NewWindow("Themed SVG bug")
os.WriteFile("disc.svg", ResDiscSvg.StaticContent, 0644)
discSvg := theme.NewThemedResource(ResDiscSvg)
filterSvg := theme.NewThemedResource(ResFilterSvg)
content := container.New(layout.NewFormLayout(),
widget.NewLabel("without themed wrapper"),
container.NewHBox(
widget.NewButtonWithIcon("", ResDiscSvg, nil),
widget.NewButtonWithIcon("", ResFilterSvg, nil),
),
widget.NewLabel("with themed wrapper"),
container.NewHBox(
widget.NewButtonWithIcon("", discSvg, nil),
widget.NewButtonWithIcon("", filterSvg, nil),
),
)
myWindow.SetContent(content)
myWindow.ShowAndRun()
}
Screenshot (on Fyne 2.4.1):
What if you remove the CSS (which we don't support)?
Pretty sure it was the CSS was the issue as I haven't seen this repro with any other icons
Another case of incorrect SVG behaviour. SVG embed code:
var resourceGameIconSvg = &fyne.StaticResource{
StaticName: "GameIcon.svg",
StaticContent: []byte(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n version=\"1.1\"\n width=\"32\"\n height=\"16\"\n viewBox=\"0 0 32 16\"\n xml:space=\"preserve\"\n id=\"svg9\"\n sodipodi:docname=\"Game Icon - test.svg\"\n inkscape:version=\"1.3.2 (091e20ef0f, 2023-11-25)\"\n xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"\n xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:svg=\"http://www.w3.org/2000/svg\"><sodipodi:namedview\n id=\"namedview9\"\n pagecolor=\"#ffffff\"\n bordercolor=\"#000000\"\n borderopacity=\"0.25\"\n inkscape:showpageshadow=\"2\"\n inkscape:pageopacity=\"0.0\"\n inkscape:pagecheckerboard=\"true\"\n inkscape:deskcolor=\"#d1d1d1\"\n inkscape:zoom=\"42.90625\"\n inkscape:cx=\"16.011653\"\n inkscape:cy=\"7.6212673\"\n inkscape:window-width=\"1920\"\n inkscape:window-height=\"1020\"\n inkscape:window-x=\"0\"\n inkscape:window-y=\"0\"\n inkscape:window-maximized=\"1\"\n inkscape:current-layer=\"svg9\" />\n<desc\n id=\"desc1\">Created with Fabric.js 5.3.0</desc>\n<defs\n id=\"defs1\">\n</defs>\n<path\n id=\"path1\"\n style=\"stroke:rgb(71, 194, 187);stroke-width:0;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:rgb(0, 0, 0);fill-rule:nonzero;opacity:1\"\n inkscape:label=\"Controller Body\"\n d=\"M -1.7416139 -1.7419103 C -2.3825695 -1.7419103 -2.9027694 -0.96161059 -2.9027694 -0.00017722134 C -2.9027694 0.96125615 -2.3825695 1.7415558 -1.7416139 1.7415558 L 1.7418524 1.7415558 C 2.3828081 1.7415558 2.9030079 0.96125615 2.9030079 -0.00017722134 C 2.9030079 -0.96161059 2.3828081 -1.7419103 1.7418524 -1.7419103 L -1.7416139 -1.7419103 z M -1.5545137 -1.306477 L -1.0597375 -1.306477 C -1.0359914 -1.306477 -1.0166477 -1.2774639 -1.0166477 -1.2418424 L -1.0166477 -0.43561048 L -0.47915977 -0.43561048 C -0.45541202 -0.43561048 -0.43607002 -0.4065949 -0.43607002 -0.37097586 L -0.43607002 0.37118838 C -0.43607002 0.40680746 -0.45541202 0.43525604 -0.47915977 0.43525604 L -1.0166477 0.43525604 L -1.0166477 1.2420549 C -1.0166477 1.2776765 -1.0359914 1.3061226 -1.0597375 1.3061226 L -1.5545137 1.3061226 C -1.5782598 1.3061226 -1.5972255 1.2776765 -1.5972255 1.2420549 L -1.5972255 0.43525604 L -2.1350914 0.43525604 C -2.1588391 0.43525604 -2.1778032 0.40680746 -2.1778032 0.37118838 L -2.1778032 -0.37097586 C -2.1778032 -0.4065949 -2.1588391 -0.43561048 -2.1350914 -0.43561048 L -1.5972255 -0.43561048 L -1.5972255 -1.2418424 C -1.5972255 -1.2774639 -1.5782598 -1.306477 -1.5545137 -1.306477 z M 1.4515635 -1.306477 C 1.611802 -1.306477 1.7418524 -1.1114013 1.7418524 -0.87104374 C 1.7418524 -0.63068614 1.611802 -0.43561048 1.4515635 -0.43561048 C 1.2913251 -0.43561048 1.1612747 -0.63068614 1.1612747 -0.87104374 C 1.1612747 -1.1114013 1.2913251 -1.306477 1.4515635 -1.306477 z M 0.87098582 -0.43561048 C 1.0312242 -0.43561048 1.1612747 -0.24053483 1.1612747 -0.00017722134 C 1.1612747 0.24018039 1.0312242 0.43525604 0.87098582 0.43525604 C 0.71074741 0.43525604 0.58069696 0.24018039 0.58069696 -0.00017722134 C 0.58069696 -0.24053483 0.71074741 -0.43561048 0.87098582 -0.43561048 z M 2.0321413 -0.43561048 C 2.1923797 -0.43561048 2.3224301 -0.24053483 2.3224301 -0.00017722134 C 2.3224301 0.24018039 2.1923797 0.43525604 2.0321413 0.43525604 C 1.8719029 0.43525604 1.7418524 0.24018039 1.7418524 -0.00017722134 C 1.7418524 -0.24053483 1.8719029 -0.43561048 2.0321413 -0.43561048 z M 1.4515635 0.43525604 C 1.611802 0.43525604 1.7418524 0.63033172 1.7418524 0.8706893 C 1.7418524 1.1110469 1.611802 1.3061226 1.4515635 1.3061226 C 1.2913251 1.3061226 1.1612747 1.1110469 1.1612747 0.8706893 C 1.1612747 0.63033172 1.2913251 0.43525604 1.4515635 0.43525604 z \"\n transform=\"matrix(5.1672668,0,0,3.4448448,15.751337,7.742798)\" />\n\n\n\n\n\n\n\n\n</svg>\n"),
}
Location of source svg: https://github.com/rad756/PlayLog/blob/main/Icons/GameIcon.svg
How SVG was created: I made it icon in vectr.com, designing it in black and white. Exported it and opened in inkscape. In inkscape I unioned all the white parts and the differenced them from the black body of the image, leaving me with this.
Using just the resource:
Using resource with theme.NewThemedResource:
I can replicate issue with the code above. I also tried exporting the file as a standard SVG (without the extra Inkscape metadata) but it behaves just the same. I have attached the smaller version below but I don't think it is of any use.
Another example of a SVG that triggers the bug (from #4712):
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="#202020" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="lucide lucide-circle-help">
<circle cx="12" cy="12" r="10" />
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
<path d="M12 17h.01" />
</svg>
While building a Material Design Icon viewer using Fyne I ran into the same issue with all 7447 icons. None of them have CSS or other weird stuff in them. Example:
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-headphones" viewBox="0 0 24 24">
<path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" />
</svg>
Loading them with fyne.LoadResourceFromPath
works okay, and as soon as I wrap the resource with theme.NewThemedResource
they disappear or become transparent. Isolated example code:
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.New()
w := a.NewWindow("Hello themed SVG issue")
r := &fyne.StaticResource{
StaticName: "headphones.svg",
StaticContent: []byte(`<svg xmlns="http://www.w3.org/2000/svg" id="mdi-headphones" viewBox="0 0 24 24"><path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" /></svg>`),
}
w.SetContent(container.NewHBox(
widget.NewIcon(r),
widget.NewIcon(theme.NewThemedResource(r)),
))
w.ShowAndRun()
}
The weird thing is that in another project I am using some of the same material design icons in a bundle I created, using theme.NewThemedResource
as well, and in that case it works fine. Maybe somehow related to how/when resources are initialized?
After my comment I started comparing the example SVG with how the SVGs in my other project look like, and I could make it work by adding width and height parameters to the above example. Hope that helps.
Thanks. Yes it seems that the library we use cannot find a sensible default for the width/height parameters if they are omitted. That's not the OP issue though, we could track it separately or open a ticket at srwiley/oksvg.