Can Compose Multiplatform already render SVG files...
# compose-web
s
Can Compose Multiplatform already render SVG files or do I need a platform specific approach for that? How will I do it on Kotlin/WASM?
1
Looks like
io.coil-kt.coil3:coil-svg
will solve that.
d
Shouldn't coil handle the rendering?
s
I guess I use it wrong, because it renders nothing.
d
Coil is for loading images from web, looking at the example from the readme. So passing svg as string is not supposed to work I guess. Passing a link to svg might work though.
And if you want to display svg from resources. I convert it to android XML vector using chat gpt and display it using the resources api.
s
There is no-longer-compiling Coil2 code around that suggests that showing an SVG from a string should be possible. > And if you want to display svg from resources. I convert it to android XML vector using chat gpt and display it using the resources api. In that regard I recommend the https://github.com/ComposeGears/Valkyrie plugin. 🙂 My use case is I want to display a visual representation of a game map of Oxygen Not Included at my current pet project https://stefan-oltmann.de/oni-seed-browser/ So the SVG input comes from an API. If there is really no other way I could change the backend, so that I can get an "myimage.svg"-URL, but I would prefer not to.
This does not work, too... So I wonder if it's working at all.
Copy code
AsyncImage(
    model = "<https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/car.svg>",
    contentDescription = null
)
Okay, that does also not work:
Copy code
val painter = rememberAsyncImagePainter(
    model = ImageRequest.Builder(PlatformContext.INSTANCE)
        .data("<https://file-examples.com/storage/fe36b23e6a66fc0679c1f86/2017/10/file_example_JPG_100kB.jpg>")
        .size(Size.ORIGINAL) // Set the target size to load the image at.
        .build()
)

Image(
    painter = painter,
    contentDescription = null
)
Coil3, an alpha, may be currently completely broken. 🤷‍♂️
m
The desktop variant of Compose can render SVG and I use that all the time. It’s located in
Copy code
androidx.compose.ui.res.SVGPainter
I copied that code and together with
Copy code
androidx.compose.ui.graphics.vector.DrawCache
I can now render SVGs on all Skia platforms. (Tested on iOS) For Android I have a different solution.
s
That sounds promising. Thank you, will try that! 🙂
Thank you, @Michael Paus. This solution works! 🙂 I added a proper copyright header and added your code to my repo: https://github.com/StefanOltmann/oni-seed-browser/blob/main/app/src/commonMain/kotlin/org/jetbrains/compose/resources/SVGPainter.kt
I'm facing the same problem here that I have with Coil3: My SVG is black. Does anyone have an idea, why not_working.svg will display black?
d
Is it appearing correctly in chrome?
It works in slack so it should be a valid svg 😄
m
Maybe you should try the original SvgPainter from Jetbrains on desktop in order to make sure the problem is not caused by my code changes.
s
Coil3 also renders to black... coincidence?
m
Ok, then it’s probably not me 😇.
s
Apple Finder renders to black, too
I think something is wrong, but I have no experience there
m
The mystery of web standards.
😁 1
1
d
I think compose doesn't handle groups that well, from what I remember.
s
One day I'll be able to look at SVG code and tell you spot on what's wrong, because I'm such an expert. That day is not today.
And unlikely tommorow. 😆
ChatGPT gave an idea: Remove the alpha channel from the color definitions. That makes it visible in Apple Finder.
Only saving it with Affinity Designer makes it readable for Compose again. 🙄
So... I guess my next question is if there is an Kotlin Multiplatform SVG cleaner/optimizer... 😄
1
Maybe not that easy. Even Java has limited options. Guess I need to try if Batik can fix the problems and if so set it up as a service.
d
Whats the difference between the working and non working svg?
s
Tell me.
a
You can use SVGO, which is a web based cleaner and optimizer. Not a permanent solution. But at least you can clean it
s
I want something reliable that always works.
a
The you need to port it. Or don’t work with SVGs if you don’t understand them
👎 1
I used batik a lot previously as a service. Works pretty well. Slow though
You can use svgo for this one svg and see if it works. There is a web interface for it. Then you see the difference between working and not working
s
Or don’t work with SVGs if you don’t understand them
Not the tone I expect here. You are not helpful at all.
a
But I am proposing a check for you to do. You immediately dismiss it as something that is not permanent
People ask you what the differences are beteeen the working and not working one and you say: “you tell me”.
Is it strange to expect a little more?
Have you tried SVGO by copying and pasting it?
And saying I am not “helpful at all” is also not a tone I’d expect.
The not_working one is showing correctly in my Finder by the way
My guesses are: • group tags are not supported • style tags are not supported, that one I have seen more. • the style tag is weirdly formatted CSS, although valid. But maybe some parser breaks there. Sadly the SVG standard is terribly implemented across targets.
👍 1
After some digging around, Skia doesn't support CSS Styles
🙏 2
So there's your issue
s
SKIA does not support external CSS styles, inlined they work. That's the issue.
Have you tried SVGO by copying and pasting it?
What are you even talking about? SVGO is a NodeJS tool in JavaScript. I'm looking for a Kotlin Multiplatform SVG cleaner/optimizer that also works on JVM.
You immediately dismiss it as something that is not permanent
Because I'm obviously looking for a permanent solution.
Thank you for the hint to https://svgo.dev If there doesn't seem to be what I'm looking for running an instance of that for the backend seems to be the next best thing I can do.
It that's a good working tool porting that to Kotlin Multiplatform and publish that as a lib sounds like another interesting side project. 🤔 You might be on to something. 👀
m
🙏 1
👍 1
s
SkiaSharp has the same issue by the way. So it's really that SKIA doesn't fully support SVG. https://github.com/mono/SkiaSharp.Extended/issues/48#issuecomment-531603910
Okay, wow, the winner of that list "svgcleaner" is already archived and nobody took over.
Looks like one should base a Kotlin Multiplatform cleaner upon svgcleaner if I look at the compatibility
And saying I am not “helpful at all” is also not a tone I’d expect.
I take that back. You have been helpful. 🙏
❤️ 1
a
No worries; Thanks we cleared that up :-)
🙂 1
SVGO has a webui btw. That is what I meant also.
But it doesn’t solve the issue
s
I now will see if I can call it using System.exec() on the server. If it has a REST API I could launch another docker container and could make a call from my main service
Found another option to optimize: https://github.com/Menecats/polybool-java Downside is that I need to reconstruct the SVG by hand, but that will take care of the duplicated paths.
Small library. If it works I consider porting it to Kotlin Multiplatform
a
https://github.com/RazrFalcon/resvg Rust based… but hey As a CLI, or C extension. Or maybe you’re able to wasmify it. Edit: it is possible to compile as wasm target It uses a subset of Skia… which is ironic
m
I’d be interested in that polybool-kotlin version too 😉😇.
🙂 1
s
I moved away from SVG. https://github.com/StefanOltmann/oni-seed-browser/blob/1b94dadc5d6305c1bc831a87847fd1bd823c1578/app/src/commonMain/kotlin/ui/MapView.kt#L69 I transfer only the paths and draw that directly on an Canvas. That saves storage.
y
s
This doesn't take a SVG bytearray. It does take a XML file you need to convert in IDEA first, I guess.
Thanks for the hint anyway, but if I would need to render SVG I would use the code Michael hinted me at.
In my specific case I found it easier to just draw the path's myself.
Of course that's only possible because I know the file will always only contain paths and not something suprising.
475 Views