Skip to content

Commit 80ceb88

Browse files
authored
Canvas Extension functions not to allocate intermediate objects (#1137)
Added some functions to Skia canvas to be able to avoid creating intermediate objects (SkRect, SkRRect, etc) on some hot paths. See [this conversation](JetBrains/compose-multiplatform-core#2543 (comment)) for the context of the PR. This is the first step to allow for Compose Ui SkiaBackedCanvas to avoid unnecessary intermediate allocations: 1. https://github.com/JetBrains/compose-multiplatform-core/blob/47af63a3986292608982f421bb345eb0a2032a98/compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt#L189 2. https://github.com/JetBrains/compose-multiplatform-core/blob/47af63a3986292608982f421bb345eb0a2032a98/compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt#L141 3. https://github.com/JetBrains/compose-multiplatform-core/blob/47af63a3986292608982f421bb345eb0a2032a98/compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt#L128 4. https://github.com/JetBrains/compose-multiplatform-core/blob/47af63a3986292608982f421bb345eb0a2032a98/compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt#L189 5. https://github.com/JetBrains/compose-multiplatform-core/blob/47af63a3986292608982f421bb345eb0a2032a98/compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt#L211 among others. **Next steps** -> open pr in Compose Ui to use these more optimized functions -> More optimizations on the Skiko side, Matrixes is a good example, CMP and Skiko are processing Matrixes 2 times, toSkiaMatrix, which basically is the same as a wrapper around FloatArray and then in the toInterop method which copies the array (unavoidable). A good optimization would be to just pass the Compose Matrix underlying `values` property which is a FloatArray that toInterop accepts and so a lot of intermediate objects and transformations could be avoided altogether
1 parent 35e297b commit 80ceb88

File tree

1 file changed

+81
-0
lines changed
  • skiko/src/commonMain/kotlin/org/jetbrains/skia

1 file changed

+81
-0
lines changed

skiko/src/commonMain/kotlin/org/jetbrains/skia/Canvas.kt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
288288
return this
289289
}
290290

291+
fun drawRect(left: Float, top: Float, right: Float, bottom: Float, paint: Paint): Canvas {
292+
Stats.onNativeCall()
293+
try {
294+
_nDrawRect(_ptr, left, top, right, bottom, getPtr(paint))
295+
} finally {
296+
reachabilityBarrier(this)
297+
reachabilityBarrier(paint)
298+
}
299+
return this
300+
}
301+
291302
fun drawRect(r: Rect, paint: Paint): Canvas {
292303
Stats.onNativeCall()
293304
try {
@@ -299,6 +310,17 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
299310
return this
300311
}
301312

313+
fun drawOval(left: Float, top: Float, right: Float, bottom: Float, paint: Paint): Canvas {
314+
Stats.onNativeCall()
315+
try {
316+
_nDrawOval(_ptr, left, top, right, bottom, getPtr(paint))
317+
} finally {
318+
reachabilityBarrier(paint)
319+
reachabilityBarrier(this)
320+
}
321+
return this
322+
}
323+
302324
fun drawOval(r: Rect, paint: Paint): Canvas {
303325
Stats.onNativeCall()
304326
try {
@@ -321,6 +343,19 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
321343
return this
322344
}
323345

346+
fun drawRRect(left: Float, top: Float, right: Float, bottom: Float, radii: FloatArray, paint: Paint): Canvas {
347+
Stats.onNativeCall()
348+
try {
349+
interopScope {
350+
_nDrawRRect(_ptr, left, top, right, bottom, toInterop(radii), radii.size, getPtr(paint))
351+
}
352+
} finally {
353+
reachabilityBarrier(paint)
354+
reachabilityBarrier(this)
355+
}
356+
return this
357+
}
358+
324359
fun drawRRect(r: RRect, paint: Paint): Canvas {
325360
Stats.onNativeCall()
326361
try {
@@ -456,6 +491,46 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
456491
return drawImageRect(image, src, dst, SamplingMode.DEFAULT, paint, strict)
457492
}
458493

494+
fun drawImageRect(
495+
image: Image,
496+
srcLeft: Float,
497+
srcTop: Float,
498+
srcRight: Float,
499+
srcBottom: Float,
500+
dstLeft: Float,
501+
dstTop: Float,
502+
dstRight: Float,
503+
dstBottom: Float,
504+
samplingMode: SamplingMode,
505+
paint: Paint?,
506+
strict: Boolean
507+
): Canvas {
508+
Stats.onNativeCall()
509+
try {
510+
_nDrawImageRect(
511+
_ptr,
512+
getPtr(image),
513+
srcLeft,
514+
srcTop,
515+
srcRight,
516+
srcBottom,
517+
dstLeft,
518+
dstTop,
519+
dstRight,
520+
dstBottom,
521+
samplingMode._packedInt1(),
522+
samplingMode._packedInt2(),
523+
getPtr(paint),
524+
strict
525+
)
526+
} finally {
527+
reachabilityBarrier(image)
528+
reachabilityBarrier(paint)
529+
reachabilityBarrier(this)
530+
}
531+
return this
532+
}
533+
459534
fun drawImageRect(
460535
image: Image,
461536
src: Rect,
@@ -1015,6 +1090,12 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
10151090
return this
10161091
}
10171092

1093+
fun clipRect(left : Float, top : Float, right: Float, bottom : Float, mode: ClipMode, antiAlias: Boolean): Canvas {
1094+
Stats.onNativeCall()
1095+
_nClipRect(_ptr, left, top, right, bottom, mode.ordinal, antiAlias)
1096+
return this
1097+
}
1098+
10181099
fun clipRect(r: Rect, mode: ClipMode): Canvas {
10191100
return clipRect(r, mode, false)
10201101
}

0 commit comments

Comments
 (0)