Unverified Commit 80ceb885 authored by ApoloApps's avatar ApoloApps Committed by GitHub

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](https://github.com/JetBrains/compose-multiplatform-core/pull/2543#discussion_r2483008621)
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
parent 35e297bd
......@@ -288,6 +288,17 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
return this
}
fun drawRect(left: Float, top: Float, right: Float, bottom: Float, paint: Paint): Canvas {
Stats.onNativeCall()
try {
_nDrawRect(_ptr, left, top, right, bottom, getPtr(paint))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(paint)
}
return this
}
fun drawRect(r: Rect, paint: Paint): Canvas {
Stats.onNativeCall()
try {
......@@ -299,6 +310,17 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
return this
}
fun drawOval(left: Float, top: Float, right: Float, bottom: Float, paint: Paint): Canvas {
Stats.onNativeCall()
try {
_nDrawOval(_ptr, left, top, right, bottom, getPtr(paint))
} finally {
reachabilityBarrier(paint)
reachabilityBarrier(this)
}
return this
}
fun drawOval(r: Rect, paint: Paint): Canvas {
Stats.onNativeCall()
try {
......@@ -321,6 +343,19 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
return this
}
fun drawRRect(left: Float, top: Float, right: Float, bottom: Float, radii: FloatArray, paint: Paint): Canvas {
Stats.onNativeCall()
try {
interopScope {
_nDrawRRect(_ptr, left, top, right, bottom, toInterop(radii), radii.size, getPtr(paint))
}
} finally {
reachabilityBarrier(paint)
reachabilityBarrier(this)
}
return this
}
fun drawRRect(r: RRect, paint: Paint): Canvas {
Stats.onNativeCall()
try {
......@@ -456,6 +491,46 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
return drawImageRect(image, src, dst, SamplingMode.DEFAULT, paint, strict)
}
fun drawImageRect(
image: Image,
srcLeft: Float,
srcTop: Float,
srcRight: Float,
srcBottom: Float,
dstLeft: Float,
dstTop: Float,
dstRight: Float,
dstBottom: Float,
samplingMode: SamplingMode,
paint: Paint?,
strict: Boolean
): Canvas {
Stats.onNativeCall()
try {
_nDrawImageRect(
_ptr,
getPtr(image),
srcLeft,
srcTop,
srcRight,
srcBottom,
dstLeft,
dstTop,
dstRight,
dstBottom,
samplingMode._packedInt1(),
samplingMode._packedInt2(),
getPtr(paint),
strict
)
} finally {
reachabilityBarrier(image)
reachabilityBarrier(paint)
reachabilityBarrier(this)
}
return this
}
fun drawImageRect(
image: Image,
src: Rect,
......@@ -1015,6 +1090,12 @@ open class Canvas internal constructor(ptr: NativePointer, managed: Boolean, int
return this
}
fun clipRect(left : Float, top : Float, right: Float, bottom : Float, mode: ClipMode, antiAlias: Boolean): Canvas {
Stats.onNativeCall()
_nClipRect(_ptr, left, top, right, bottom, mode.ordinal, antiAlias)
return this
}
fun clipRect(r: Rect, mode: ClipMode): Canvas {
return clipRect(r, mode, false)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment