Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use TextMeasurer in application scope (LocalFontFamilyResolver / LocalLayoutDirection not present) #3289

Closed
kirill-grouchnikov opened this issue Jun 26, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@kirill-grouchnikov
Copy link

Desktop version 1.4.0 on macOS

Run this:

@OptIn(ExperimentalTextApi::class)
fun main() = application {
    val textMeasurer = rememberTextMeasurer()
    Window(onCloseRequest = ::exitApplication) {
    }
}

And it crashes with

Exception in thread "main" java.lang.IllegalStateException: CompositionLocal LocalFontFamilyResolver not present
	at androidx.compose.ui.platform.CompositionLocalsKt.noLocalProvidedFor(CompositionLocals.kt:219)
	at androidx.compose.ui.platform.CompositionLocalsKt.access$noLocalProvidedFor(CompositionLocals.kt:1)
	at androidx.compose.ui.platform.CompositionLocalsKt$LocalFontFamilyResolver$1.invoke(CompositionLocals.kt:110)
	at androidx.compose.ui.platform.CompositionLocalsKt$LocalFontFamilyResolver$1.invoke(CompositionLocals.kt:109)
	at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
	at androidx.compose.runtime.LazyValueHolder.getCurrent(ValueHolders.kt:29)
	at androidx.compose.runtime.LazyValueHolder.getValue(ValueHolders.kt:31)
	at androidx.compose.runtime.ComposerImpl.resolveCompositionLocal(Composer.kt:2070)
	at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:2038)
	at androidx.compose.ui.text.TextMeasurerHelperKt.rememberTextMeasurer(TextMeasurerHelper.kt:53)
	at org.pushingpixels.aurora.demo.ComposableSingletons$MainKt$lambda-2$1.invoke(main.kt:10)
	at org.pushingpixels.aurora.demo.ComposableSingletons$MainKt$lambda-2$1.invoke(main.kt:9)
	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.window.Application_desktopKt$application$1$1.invoke(Application.desktop.kt:115)
	at androidx.compose.ui.window.Application_desktopKt$application$1$1.invoke(Application.desktop.kt:114)
	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.window.Application_desktopKt$awaitApplication$2$1$2$1$1.invoke(Application.desktop.kt:226)
	at androidx.compose.ui.window.Application_desktopKt$awaitApplication$2$1$2$1$1.invoke(Application.desktop.kt:225)
	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.window.Application_desktopKt$awaitApplication$2$1$2$1.invoke(Application.desktop.kt:221)
	at androidx.compose.ui.window.Application_desktopKt$awaitApplication$2$1$2$1.invoke(Application.desktop.kt:219)
	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.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:313)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
	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)

Why is LocalFontFamilyResolver.current crashing in the application scope? And the same for LocalLayoutDirection.current

@kirill-grouchnikov kirill-grouchnikov added bug Something isn't working submitted labels Jun 26, 2023
@m-sasha
Copy link
Member

m-sasha commented Jun 26, 2023

Indeed we're currently providing all the common composition locals only inside the window scope.

@m-sasha
Copy link
Member

m-sasha commented Jun 26, 2023

I'm not sure whether this should be considered a bug or a feature request.

@Walingar Walingar added enhancement New feature or request and removed bug Something isn't working submitted labels Jun 26, 2023
@kirill-grouchnikov
Copy link
Author

Another example where this is needed outside of the window scope.

The recently added functions in TextPainter to draw text in a multiplatform way require either TextMeasurer or TextLayoutResult. The later needs FontFamily.Resolver to be created. So in both cases, in order to use DrawScope.drawText we need these common composition locals to be available.

A common example of using DrawScope.drawText outside of the window scope would be to dynamically create things like icons and overlay them with text elements (or dynamically generate icons or images with text elements) for subsequent use as icons on buttons or somewhere else.

@okushnikov
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants