Skip to content

Commit 3104de1

Browse files
authored
Migrate to less allocations function overloads from Skiko (JetBrains#2731)
After Skiko version upgrade, move all functions in the repo to avoid allocating intermediate objects using specific overloads in Skiko Also, there's a few micro optimizations here and there ->Avoiding iterators whenever possible -> Using fastRoundToInt in desktop platform to avoid more allocations than necessary ->indexOfFirst to manually doing it with for loop (i just sent a pr to Google to be able to use a fast* function overload instead) ->Added IntSize.toRect to avoid several (packing/unpacking + allocations) since rect is a data class ->Avoid crossing the js2wasm border in same function in different places and reuse those values whenever possible -> Some Intellij inspection recommendations such as if/else null to ifEmpty; object construction to fun interface representation; needRedraw -> needRender; or Companion middle package removal since its redundant ## Release Notes N/A
2 parents e3907ff + 04ab6dc commit 3104de1

29 files changed

Lines changed: 320 additions & 128 deletions

File tree

compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSource.skiko.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,12 @@ internal actual class CacheDrawScopeDragShadowCallback {
8282
onDrawWithContent {
8383
val pictureRecorder = PictureRecorder()
8484
val pictureCanvas = pictureRecorder
85-
.beginRecording(Rect.makeWH(width, height))
85+
.beginRecording(
86+
0f,
87+
0f,
88+
width,
89+
height
90+
)
8691
.asComposeCanvas()
8792
draw(
8893
density = this,

compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedPath.skiko.kt

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,43 +130,108 @@ internal class SkiaBackedPath(
130130
forceMoveTo: Boolean
131131
) {
132132
internalPath.arcTo(
133-
rect.toSkiaRect(),
133+
rect.left,
134+
rect.top,
135+
rect.right,
136+
rect.bottom,
134137
startAngleDegrees,
135138
sweepAngleDegrees,
136139
forceMoveTo
137140
)
138141
}
139142

140143
override fun addRect(rect: Rect) {
141-
internalPath.addRect(rect.toSkiaRect(), PathDirection.COUNTER_CLOCKWISE)
144+
internalPath.addRect(
145+
rect.left,
146+
rect.top,
147+
rect.right,
148+
rect.bottom,
149+
PathDirection.COUNTER_CLOCKWISE
150+
)
142151
}
143152

144153
override fun addRect(rect: Rect, direction: Path.Direction) {
145-
internalPath.addRect(rect.toSkiaRect(), direction.toSkiaPathDirection())
154+
internalPath.addRect(
155+
rect.left,
156+
rect.top,
157+
rect.right,
158+
rect.bottom,
159+
direction.toSkiaPathDirection()
160+
)
146161
}
147162

148163
override fun addOval(oval: Rect) {
149-
internalPath.addOval(oval.toSkiaRect(), PathDirection.COUNTER_CLOCKWISE)
164+
internalPath.addOval(
165+
oval.left,
166+
oval.top,
167+
oval.right,
168+
oval.bottom,
169+
PathDirection.COUNTER_CLOCKWISE
170+
)
150171
}
151172

152173
override fun addOval(oval: Rect, direction: Path.Direction) {
153-
internalPath.addOval(oval.toSkiaRect(), direction.toSkiaPathDirection())
174+
internalPath.addOval(
175+
oval.left,
176+
oval.top,
177+
oval.right,
178+
oval.bottom,
179+
direction.toSkiaPathDirection()
180+
)
154181
}
155182

156183
override fun addRoundRect(roundRect: RoundRect) {
157-
internalPath.addRRect(roundRect.toSkiaRRect(), PathDirection.COUNTER_CLOCKWISE)
184+
internalPath.addRRect(
185+
roundRect.left,
186+
roundRect.top,
187+
roundRect.right,
188+
roundRect.bottom,
189+
floatArrayOf(
190+
roundRect.topLeftCornerRadius.x,
191+
roundRect.topLeftCornerRadius.y,
192+
roundRect.topRightCornerRadius.x,
193+
roundRect.topRightCornerRadius.y,
194+
roundRect.bottomRightCornerRadius.x,
195+
roundRect.bottomRightCornerRadius.y,
196+
roundRect.bottomLeftCornerRadius.x,
197+
roundRect.bottomLeftCornerRadius.y
198+
),
199+
PathDirection.COUNTER_CLOCKWISE
200+
)
158201
}
159202

160203
override fun addRoundRect(roundRect: RoundRect, direction: Path.Direction) {
161-
internalPath.addRRect(roundRect.toSkiaRRect(), direction.toSkiaPathDirection())
204+
internalPath.addRRect(
205+
roundRect.left,
206+
roundRect.top,
207+
roundRect.right,
208+
roundRect.bottom,
209+
floatArrayOf(
210+
roundRect.topLeftCornerRadius.x,
211+
roundRect.topLeftCornerRadius.y,
212+
roundRect.topRightCornerRadius.x,
213+
roundRect.topRightCornerRadius.y,
214+
roundRect.bottomRightCornerRadius.x,
215+
roundRect.bottomRightCornerRadius.y,
216+
roundRect.bottomLeftCornerRadius.x,
217+
roundRect.bottomLeftCornerRadius.y
218+
),
219+
direction.toSkiaPathDirection()
220+
)
162221
}
163222

164223
override fun addArcRad(oval: Rect, startAngleRadians: Float, sweepAngleRadians: Float) {
165224
addArc(oval, degrees(startAngleRadians), degrees(sweepAngleRadians))
166225
}
167226

168227
override fun addArc(oval: Rect, startAngleDegrees: Float, sweepAngleDegrees: Float) {
169-
internalPath.addArc(oval.toSkiaRect(), startAngleDegrees, sweepAngleDegrees)
228+
internalPath.addArc(
229+
oval.left,
230+
oval.top,
231+
oval.right,
232+
oval.bottom,
233+
startAngleDegrees, sweepAngleDegrees
234+
)
170235
}
171236

172237
override fun addPath(path: Path, offset: Offset) {

compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/layer/SkiaGraphicsLayer.skiko.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ import androidx.compose.ui.graphics.drawscope.draw
4040
import androidx.compose.ui.graphics.nativeCanvas
4141
import androidx.compose.ui.graphics.toArgb
4242
import androidx.compose.ui.graphics.toSkia
43-
import androidx.compose.ui.graphics.toSkiaRRect
44-
import androidx.compose.ui.graphics.toSkiaRect
4543
import androidx.compose.ui.unit.Density
4644
import androidx.compose.ui.unit.IntOffset
4745
import androidx.compose.ui.unit.IntSize
@@ -376,10 +374,31 @@ actual class GraphicsLayer internal constructor(
376374
renderNode.setClipPath(null)
377375
} else {
378376
renderNode.clip = clip
379-
val tmpOutline = outline
380-
when (tmpOutline) {
381-
is Outline.Rectangle -> renderNode.setClipRect(tmpOutline.rect.toSkiaRect(), antiAlias = true)
382-
is Outline.Rounded -> renderNode.setClipRRect(tmpOutline.roundRect.toSkiaRRect(), antiAlias = true)
377+
when (val tmpOutline = outline) {
378+
is Outline.Rectangle -> renderNode.setClipRect(
379+
tmpOutline.rect.left,
380+
tmpOutline.rect.top,
381+
tmpOutline.rect.right,
382+
tmpOutline.rect.bottom,
383+
antiAlias = true
384+
)
385+
is Outline.Rounded -> renderNode.setClipRRect(
386+
tmpOutline.roundRect.left,
387+
tmpOutline.roundRect.top,
388+
tmpOutline.roundRect.right,
389+
tmpOutline.roundRect.bottom,
390+
floatArrayOf(
391+
tmpOutline.roundRect.topLeftCornerRadius.x,
392+
tmpOutline.roundRect.topLeftCornerRadius.y,
393+
tmpOutline.roundRect.topRightCornerRadius.x,
394+
tmpOutline.roundRect.topRightCornerRadius.y,
395+
tmpOutline.roundRect.bottomRightCornerRadius.x,
396+
tmpOutline.roundRect.bottomRightCornerRadius.y,
397+
tmpOutline.roundRect.bottomLeftCornerRadius.x,
398+
tmpOutline.roundRect.bottomLeftCornerRadius.y
399+
),
400+
antiAlias = true
401+
)
383402
is Outline.Generic -> renderNode.setClipPath(tmpOutline.path.asSkiaPath(), antiAlias = true)
384403
}
385404
}

compose/ui/ui-graphics/src/skikoTest/kotlin/androidx/compose/ui/graphics/layer/SkiaGraphicsLayerTest.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,12 +1044,14 @@ class SkiaGraphicsLayerTest {
10441044
}
10451045
}
10461046
surface.flushAndSubmit(true)
1047-
val area =
1048-
IRect.makeWH(
1047+
val imageBitmap = surface
1048+
.makeImageSnapshot(
1049+
0,
1050+
0,
10491051
if (entireScene) TEST_WIDTH * 2 else TEST_WIDTH,
10501052
if (entireScene) TEST_HEIGHT * 2 else TEST_HEIGHT
1051-
)
1052-
val imageBitmap = surface.makeImageSnapshot(area)!!.toComposeImageBitmap()
1053+
)!!
1054+
.toComposeImageBitmap()
10531055
verify?.invoke(imageBitmap.toPixelMap())
10541056
} finally {
10551057
surface.close()

compose/ui/ui-graphics/src/skikoTest/kotlin/androidx/compose/ui/graphics/shadow/SkiaShadowTestHelper.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,14 @@ fun shadowTest(block: DrawScope.() -> Unit, verify: (PixelMap) -> Unit) {
5353
block()
5454
}
5555
surface.flushAndSubmit(true)
56-
val area =
57-
IRect.makeWH(TEST_WIDTH, TEST_HEIGHT)
58-
val imageBitmap = surface.makeImageSnapshot(area)!!.toComposeImageBitmap()
56+
val imageBitmap = surface
57+
.makeImageSnapshot(
58+
0,
59+
0,
60+
TEST_WIDTH,
61+
TEST_HEIGHT
62+
)!!
63+
.toComposeImageBitmap()
5964
verify(imageBitmap.toPixelMap())
6065
} finally {
6166
surface.close()

compose/ui/ui-test/src/skikoMain/kotlin/androidx/compose/ui/test/ComposeUiTest.skiko.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,12 @@ open class SkikoComposeUiTest @InternalTestApi constructor(
459459

460460
fun captureToImage(semanticsNode: SemanticsNode): ImageBitmap {
461461
val rect = semanticsNode.boundsInWindow
462-
val iRect = IRect.makeLTRB(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt())
463-
val image = surface.makeImageSnapshot(iRect)
462+
val image = surface.makeImageSnapshot(
463+
rect.left.toInt(),
464+
rect.top.toInt(),
465+
rect.right.toInt(),
466+
rect.bottom.toInt()
467+
)
464468
return image!!.toComposeImageBitmap()
465469
}
466470

compose/ui/ui-test/src/skikoMain/kotlin/androidx/compose/ui/test/InputDispatcher.skiko.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.compose.ui.input.pointer.PointerType
2828
import androidx.compose.ui.node.RootForTest
2929
import androidx.compose.ui.platform.PlatformRootForTest
3030
import androidx.compose.ui.scene.ComposeScenePointer
31+
import androidx.compose.ui.util.fastForEach
3132

3233
@OptIn(InternalComposeUiApi::class)
3334
internal actual fun createInputDispatcher(
@@ -300,7 +301,7 @@ internal class SkikoInputDispatcher(
300301
override fun flush() {
301302
val copy = batchedEvents.toList()
302303
batchedEvents.clear()
303-
for (event in copy) {
304+
copy.fastForEach { event ->
304305
advanceClockTime(event.eventTime - currentClockTime)
305306
currentClockTime = event.eventTime
306307
event.action()

compose/ui/ui-text/src/desktopMain/kotlin/androidx/compose/ui/text/platform/JetBrainsRuntimeFontFamilies.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import androidx.compose.ui.text.font.FontFamily
2020
import androidx.compose.ui.text.font.FontListFontFamily
2121
import androidx.compose.ui.text.font.FontStyle
2222
import androidx.compose.ui.text.font.FontWeight
23+
import androidx.compose.ui.util.fastDistinctBy
24+
import androidx.compose.ui.util.fastMap
2325
import java.io.File
2426
import kotlin.io.path.Path
2527
import kotlin.io.path.absolutePathString
@@ -90,7 +92,7 @@ internal object JetBrainsRuntimeFontFamilies {
9092
val embeddedFontFileNames = field.get(fontManager) as HashSet<String>
9193
val embeddedFontPaths = embeddedFontFileNames.map { jbrEmbeddedFontsPath.resolve(it) }
9294
.sortedBy { it.absolutePathString() }
93-
.distinctBy { it.absolutePathString() }
95+
.fastDistinctBy { it.absolutePathString() }
9496

9597
embeddedFontPaths.asSequence()
9698
.map { path ->
@@ -110,7 +112,7 @@ internal object JetBrainsRuntimeFontFamilies {
110112
.distinctBy { (_, font) -> font.file.absolutePath }
111113
.groupBy { (familyName, _) -> familyName }
112114
.forEach { (identity, fileFonts) ->
113-
val fontFamily = FontListFontFamily(fileFonts.map { it.second })
115+
val fontFamily = FontListFontFamily(fileFonts.fastMap { it.second })
114116
embeddedFamilies += identity.lowercase() to fontFamily
115117
}
116118
} finally {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ internal class SkiaParagraph(
172172
)
173173
val path = Path()
174174
for (b in boxes) {
175-
path.asSkiaPath().addRect(b.rect)
175+
path.asSkiaPath().addRect(b.rect.left, b.rect.top, b.rect.right, b.rect.bottom)
176176
}
177177
return path
178178
}

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/Utils.desktop.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.compose.ui.geometry.Rect
2020
import androidx.compose.ui.graphics.Color
2121
import androidx.compose.ui.unit.Density
2222
import androidx.compose.ui.unit.IntRect
23+
import androidx.compose.ui.util.fastRoundToInt
2324
import java.awt.Component
2425
import java.awt.EventQueue
2526
import java.awt.Graphics
@@ -77,10 +78,10 @@ internal fun IntRect.toAwtRectangle(density: Density = Density(1f)) = toAwtRecta
7778
*/
7879
internal fun Rect.toAwtRectangleRounded(density: Density): Rectangle {
7980
val densityValue = density.density
80-
val left = (this.left / densityValue).roundToInt()
81-
val top = (this.top / densityValue).roundToInt()
82-
val right = (this.right / densityValue).roundToInt()
83-
val bottom = (this.bottom / densityValue).roundToInt()
81+
val left = (this.left / densityValue).fastRoundToInt()
82+
val top = (this.top / densityValue).fastRoundToInt()
83+
val right = (this.right / densityValue).fastRoundToInt()
84+
val bottom = (this.bottom / densityValue).fastRoundToInt()
8485
return Rectangle(left, top, right - left, bottom - top)
8586
}
8687

0 commit comments

Comments
 (0)