Skip to content

Commit 612833a

Browse files
authored
Fallback to empty line metrics in case if skia doesn't return real metrics (#2599)
[CMP-9345](https://youtrack.jetbrains.com/issue/CMP-9345) Compose application crashes when selecting text that only contains inline content ## Release Notes ### Fixes - Multiple Platforms - Fix crash when selecting text that only contains inline content
1 parent 682fae0 commit 612833a

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

compose/ui/ui-text/src/desktopTest/kotlin/androidx/compose/ui/text/DesktopParagraphTest.kt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,56 @@ class DesktopParagraphTest {
483483
.isEqualTo(1)
484484
}
485485

486+
@Test
487+
fun getLineForOffset_empty() {
488+
val text = ""
489+
val paragraph = simpleParagraph(
490+
text = text,
491+
style = TextStyle(fontSize = 50.sp)
492+
)
493+
494+
assertThat(paragraph.getLineForOffset(0))
495+
.isEqualTo(0)
496+
}
497+
498+
@Test
499+
fun getLineForOffset_withOnlyPlaceholder() {
500+
val text = buildAnnotatedString {
501+
pushStringAnnotation("test", "a")
502+
append("\uFFFD")
503+
pop()
504+
}
505+
506+
val intrinsics = ParagraphIntrinsics(
507+
text = text.text,
508+
style = TextStyle(
509+
fontSize = 50.sp,
510+
fontFamily = fontFamilyMeasureFont,
511+
),
512+
annotations = listOf(
513+
AnnotatedString.Range(
514+
item = StringAnnotation("a"),
515+
start = 0,
516+
end = 1,
517+
tag = "test",
518+
)
519+
),
520+
placeholders = listOf(
521+
AnnotatedString.Range(
522+
item = Placeholder(40.0.sp, 16.0.sp, PlaceholderVerticalAlign.Center),
523+
start = 0,
524+
end = 1,
525+
tag = "test",
526+
)
527+
),
528+
density = defaultDensity,
529+
fontFamilyResolver = fontFamilyResolver,
530+
)
531+
val paragraph = simpleParagraph(intrinsics)
532+
assertThat(paragraph.getLineForOffset(0))
533+
.isEqualTo(0)
534+
}
535+
486536
@Test
487537
fun getLineEnd() {
488538
with(defaultDensity) {

compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/SkiaParagraph.skiko.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,18 @@ internal class SkiaParagraph(
332332
val lineMetrics = if (text.isEmpty()) {
333333
layouter.emptyLineMetrics(paragraph)
334334
} else {
335-
// This creates a new objects every time
335+
// This getter creates a new object every time
336336
paragraph.lineMetrics
337+
// In the case of annotated text where everything is replaced by placeholders,
338+
// the line metrics may be empty
339+
.ifEmpty { layouter.emptyLineMetrics(paragraph) }
337340
}
338341

339342
val fontMetrics = defaultFont.metrics
340-
if (lineMetrics.isNotEmpty()) {
341-
lineMetrics[0] = lineMetrics[0]
342-
.trimFirstAscent(fontMetrics, layouter.textStyle)
343-
lineMetrics[lineMetrics.size - 1] = lineMetrics[lineMetrics.size - 1]
344-
.trimLastDescent(fontMetrics, layouter.textStyle)
345-
}
343+
lineMetrics[0] = lineMetrics[0]
344+
.trimFirstAscent(fontMetrics, layouter.textStyle)
345+
lineMetrics[lineMetrics.size - 1] = lineMetrics[lineMetrics.size - 1]
346+
.trimLastDescent(fontMetrics, layouter.textStyle)
346347

347348
return lineMetrics
348349
}

0 commit comments

Comments
 (0)