JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.95k stars 1.16k forks source link

loadSvgPainter crashes with unspecific error message #3268

Open exaV opened 1 year ago

exaV commented 1 year ago

Describe the bug This following code tries to load an svg and fails with the error message "Can't wrap nullptr". I concede that the svg was malformed, but the error message was not helpful at all. Also in Chrome the same svg works just fine.

import androidx.compose.ui.res.loadSvgPainter
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.singleWindowApplication

fun main() = singleWindowApplication(
    title = "Example",
    state = WindowState(size = DpSize(800.dp, 800.dp))
) {
    loadSvgPainter(badInput.byteInputStream(), Density(1f))
}

// language=SVG
val badInput: String = """
    <svg viewBox="-2 -2 22 22" style="width: 100%; height: auto; background: brown" xmlns="http://www.w3.org/2000/svg">
    <rect x=0 y="0" width="18" height="18"/>      
    </svg>
""".trimIndent()

The error in the svg is the missing quotes around the first 0 in <rect x=0 y="0"

Affected platforms Select one of the platforms below:

Versions

To Reproduce

  1. Run the code from above on jvm

Expected behavior The program should either work or crash with a sensible error mesage (e.g. "malformed svg").

Full Stacktrace:

Exception in thread "main" java.lang.RuntimeException: Can't wrap nullptr
    at org.jetbrains.skia.impl.Native.<init>(Native.jvm.kt:40)
    at org.jetbrains.skia.impl.Managed.<init>(Managed.jvm.kt:11)
    at org.jetbrains.skia.impl.RefCnt.<init>(RefCnt.jvm.kt:6)
    at org.jetbrains.skia.svg.SVGDOM.<init>(SVGDOM.kt:17)
    at org.jetbrains.skia.svg.SVGDOM.<init>(SVGDOM.kt:24)
    at androidx.compose.ui.res.DesktopSvgResources_desktopKt.loadSvgPainter(DesktopSvgResources.desktop.kt:56)
    at ComposableSingletons$MainKt$lambda-1$1.invoke(Main.kt:24)
    at ComposableSingletons$MainKt$lambda-1$1.invoke(Main.kt:22)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.ui.awt.ComposeWindow$setContent$5.invoke(ComposeWindow.desktop.kt:126)
    at androidx.compose.ui.awt.ComposeWindow$setContent$5.invoke(ComposeWindow.desktop.kt:125)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.ui.awt.ComposeWindowDelegate.WindowContentLayout(ComposeWindowDelegate.desktop.kt:163)
    at androidx.compose.ui.awt.ComposeWindowDelegate.access$WindowContentLayout(ComposeWindowDelegate.desktop.kt:49)
    at androidx.compose.ui.awt.ComposeWindowDelegate$setContent$3$1.invoke(ComposeWindowDelegate.desktop.kt:152)
    at androidx.compose.ui.awt.ComposeWindowDelegate$setContent$3$1.invoke(ComposeWindowDelegate.desktop.kt:151)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.awt.ComposeWindowDelegate$setContent$3.invoke(ComposeWindowDelegate.desktop.kt:148)
    at androidx.compose.ui.awt.ComposeWindowDelegate$setContent$3.invoke(ComposeWindowDelegate.desktop.kt:147)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.ComposeScene$setContent$5.invoke(ComposeScene.skiko.kt:377)
    at androidx.compose.ui.ComposeScene$setContent$5.invoke(ComposeScene.skiko.kt:376)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:194)
    at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2$1.invoke(Wrapper.skiko.kt:47)
    at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2$1.invoke(Wrapper.skiko.kt:46)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248)
    at androidx.compose.ui.platform.Wrapper_skikoKt.provide(Wrapper.skiko.kt:61)
    at androidx.compose.ui.platform.Wrapper_skikoKt.access$provide(Wrapper.skiko.kt:1)
    at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2.invoke(Wrapper.skiko.kt:46)
    at androidx.compose.ui.platform.Wrapper_skikoKt$setContent$2.invoke(Wrapper.skiko.kt:45)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
    at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:37)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3353)
    at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3343)
    at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
    at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source)
    at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3343)
    at androidx.compose.runtime.ComposerImpl.composeContent$runtime(Composer.kt:3278)
    at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:587)
    at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:966)
    at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519)
    at androidx.compose.ui.platform.Wrapper_skikoKt.setContent(Wrapper.skiko.kt:45)
    at androidx.compose.ui.ComposeScene.setContent$ui(ComposeScene.skiko.kt:373)
    at androidx.compose.ui.ComposeScene.setContent$ui$default(ComposeScene.skiko.kt:351)
    at androidx.compose.ui.awt.ComposeLayer$setContent$3$1.invoke(ComposeLayer.desktop.kt:416)
    at androidx.compose.ui.awt.ComposeLayer$setContent$3$1.invoke(ComposeLayer.desktop.kt:415)
    at androidx.compose.ui.awt.ComposeLayer.catchExceptions(ComposeLayer.desktop.kt:109)
    at androidx.compose.ui.awt.ComposeLayer.access$catchExceptions(ComposeLayer.desktop.kt:87)
    at androidx.compose.ui.awt.ComposeLayer$setContent$3.invoke(ComposeLayer.desktop.kt:415)
    at androidx.compose.ui.awt.ComposeLayer$setContent$3.invoke(ComposeLayer.desktop.kt:414)
    at androidx.compose.ui.awt.ComposeLayer.initContent(ComposeLayer.desktop.kt:430)
    at androidx.compose.ui.awt.ComposeLayer.access$initContent(ComposeLayer.desktop.kt:87)
    at androidx.compose.ui.awt.ComposeLayer$ComponentImpl.addNotify(ComposeLayer.desktop.kt:225)
    at java.desktop/java.awt.Container.addNotify(Container.java:2804)
    at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
    at androidx.compose.ui.awt.ComposeWindowDelegate$_pane$1.addNotify(ComposeWindowDelegate.desktop.kt:86)
    at java.desktop/java.awt.Container.addNotify(Container.java:2804)
    at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
    at java.desktop/java.awt.Container.addNotify(Container.java:2804)
    at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
    at java.desktop/java.awt.Container.addNotify(Container.java:2804)
    at java.desktop/javax.swing.JComponent.addNotify(JComponent.java:4839)
    at java.desktop/javax.swing.JRootPane.addNotify(JRootPane.java:729)
    at java.desktop/java.awt.Container.addNotify(Container.java:2804)
    at java.desktop/java.awt.Window.addNotify(Window.java:791)
    at java.desktop/java.awt.Frame.addNotify(Frame.java:495)
    at java.desktop/java.awt.Window.pack(Window.java:829)
    at androidx.compose.ui.util.Windows_desktopKt.setSizeImpl-6HolHcs(Windows.desktop.kt:115)
    at androidx.compose.ui.util.Windows_desktopKt.setSizeSafely-hQcJfNw(Windows.desktop.kt:54)
    at androidx.compose.ui.window.Window_desktopKt$Window$5.invoke(Window.desktop.kt:235)
    at androidx.compose.ui.window.Window_desktopKt$Window$5.invoke(Window.desktop.kt:172)
    at androidx.compose.ui.window.Window_desktopKt$Window$11$1.invoke(Window.desktop.kt:416)
    at androidx.compose.ui.window.Window_desktopKt$Window$11$1.invoke(Window.desktop.kt:410)
    at androidx.compose.ui.window.AwtWindow_desktopKt$AwtWindow$3.invoke(AwtWindow.desktop.kt:82)
    at androidx.compose.ui.window.AwtWindow_desktopKt$AwtWindow$3.invoke(AwtWindow.desktop.kt:80)
    at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2$performUpdate$1.invoke(UpdateEffect.desktop.kt:59)
    at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2$performUpdate$1.invoke(UpdateEffect.desktop.kt:55)
    at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2201)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:238)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
    at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
    at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:234)
    at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke$performUpdate(UpdateEffect.desktop.kt:55)
    at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke(UpdateEffect.desktop.kt:64)
    at androidx.compose.ui.util.UpdateEffect_desktopKt$UpdateEffect$2.invoke(UpdateEffect.desktop.kt:47)
    at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:81)
    at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1105)
    at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:820)
    at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:842)
    at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:994)
    at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519)
    at androidx.compose.ui.window.Application_desktopKt$awaitApplication$2$1$2.invokeSuspend(Application.desktop.kt:219)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:741)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.