Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
de99b4e
Cache Matrix class in SkiaBackedPath to mimic Android behaviour
ApoloApps Jun 11, 2026
250ac4d
Cache RoundedRect FloatArray object to avoid allocating it each time.…
ApoloApps Jun 11, 2026
78e6ee1
Add toFloatArray method that avoids iterator allocation (compiles to …
ApoloApps Jun 11, 2026
329ba77
Adds CanvasHolder class to avoid creating a new SkiaBackedCanvas obje…
ApoloApps Jun 11, 2026
ebc198a
Merge branch 'jb-main' into followupMatrixSkiko
ApoloApps Jun 12, 2026
eddb40b
Fix after rebase
ApoloApps Jun 12, 2026
fd6b122
Avoid Rect allocations on extremely hot paths. (each frame, single or…
ApoloApps Jun 15, 2026
211369e
Reduce number of copies in SyntheticEventSender and use Primitive Col…
ApoloApps Jun 15, 2026
9db20d7
Change comment mentioning Android Canvas
ApoloApps Jun 16, 2026
56f34cf
Fix crash in method setComposingRegion (#3112)
ASalavei Jun 12, 2026
3b98945
Update iOS version in GH actions (#3115)
janinadavydova Jun 12, 2026
a0a2e85
Fix lifecycle state handling for ComposeContainer (#3118)
ASalavei Jun 15, 2026
694a400
Fix incorrect frames order on high load (#3122)
ASalavei Jun 16, 2026
56920dc
Extend compose ios instrumented tests runners matrix (#3125)
svastven Jun 17, 2026
400f7af
`DeprecationLevel.ERROR` for skiko-specific types in ui-graphics API …
MatkovIvan Jun 17, 2026
b19a6f4
iOS instrumented tests for textfield menu items availability (#3129)
janinadavydova Jun 18, 2026
edc0857
Align frame snapshot/invalidation with Android's model (#3096)
MatkovIvan Jun 18, 2026
fccbf4e
Web: Enhance scroll behavior by distinguishing trackpad gestures and …
terrakok Jun 18, 2026
869255f
Removed caret snapping inside grapheme clusters hack (#3049)
mazunin-v-jb Jun 18, 2026
93b3ad1
Update skiko to 0.149.0 (#3124)
hub-bla Jun 18, 2026
4a60e33
Fix iOS 26 swipe-back conflict with horizontal Compose scrollables (#…
svastven Jun 18, 2026
65d526d
[web] style backing field inputs in shadow css definitions (#3133)
Schahen Jun 18, 2026
34e7fbf
Copy lifecycle from f68fb752573
igordmn Jun 18, 2026
5432759
artifactRedirection.version.androidx.lifecycle=2.11.0
igordmn Jun 18, 2026
272adbe
Web: Fix Safari wheel event (#3135)
terrakok Jun 18, 2026
e69ba78
Copy compose-material3 from fb82b6431c9
igordmn Jun 18, 2026
dee46c0
artifactRedirection.version.androidx.compose.material3=1.5.0-alpha22
igordmn Jun 18, 2026
7a55736
SkikoMenu. Get rid of transformOriginState
igordmn Jun 18, 2026
37f90c6
Dump API
igordmn Jun 18, 2026
38b9288
Fix ExposedDropdownMenuTest.edm_withScrolledContent
igordmn Jun 18, 2026
9ad050b
Fix testFocusableAboveKeyboardInModalBottomSheet on iOS
igordmn Jun 18, 2026
642ca62
Update skiko to 0.150.0 (#3138)
hub-bla Jun 19, 2026
d82f0c1
Copy compose from 4b6028d232d
igordmn Jun 18, 2026
ac7baac
Stub ":appcompat:appcompat" Android project
igordmn Jun 18, 2026
ca5ea98
Dump API
igordmn Jun 19, 2026
989c9b1
Fix Modifier.textFieldOverlay
igordmn Jun 19, 2026
bd4f401
compose:ui: Disable isTriggerMoveEventsWhenLocationHasNotChangedEnabled
XSJoJo Jun 16, 2026
aadd326
Copy navigation3 from 1f0933dbe56
igordmn Jun 18, 2026
5693eba
artifactRedirection.version.androidx.navigation3=1.2.0-alpha03
igordmn Jun 18, 2026
28c7756
Change the native keyCode for `Key.NumPadDot` to `KeyEvent.VK_DECIMAL…
m-sasha Jun 22, 2026
655390a
Remove `SkikoSelectionModifierElement` (#3141)
m-sasha Jun 22, 2026
bf4631b
Implement `GraphicsLayer.setOutsets` for non-Android platforms (#3144)
MatkovIvan Jun 23, 2026
b8752a7
Fix some event-dispatching tests and move them into a separate file (…
m-sasha Jun 23, 2026
358b728
Web: deliver both scroll axes in wheel events (fix diagonal scroll) (…
terrakok Jun 23, 2026
22ce9a3
Introduce `ComposeDesktopEntryPoint` interface (#3140)
m-sasha Jun 23, 2026
ae753e6
Fix skiko text helpers visibility (#3150)
MatkovIvan Jun 23, 2026
25bffda
Support `MeshGradientPainter` in `Modifier.paint` (#3143)
MatkovIvan Jun 23, 2026
2ba56cc
Fix invalidation during removing the layer (#3146)
MatkovIvan Jun 23, 2026
e1d75f3
Implement `PrefetchScheduler` for iOS (#3149)
svastven Jun 23, 2026
e89db56
Remove old/unused publications (#3151)
MatkovIvan Jun 23, 2026
192c90b
Retry loading fallback fonts in case of network errors (#3152)
terrakok Jun 23, 2026
7c9e6ef
Support Locale and Verbatim VoiceOver annotation (#3145)
ASalavei Jun 23, 2026
eebc779
artifact redirection rework (#3121)
shishkin-pavel Jun 23, 2026
f7487a8
Fix coordinate conversion for WINDOW layers (#3154)
MatkovIvan Jun 24, 2026
c13a064
Refactor frame rate voting management (#3148)
svastven Jun 24, 2026
68991cc
Check accessibleChild for `null` in `defaultAccessibilityFocusTarget`…
m-sasha Jun 25, 2026
2ea252f
Don't set alwaysOnTop in WindowComposeSceneLayer (#3153)
m-sasha Jun 25, 2026
57ef0b4
Fix printing `GlobalSnapshotManager` concurrent registrations warning…
MatkovIvan Jun 26, 2026
b478d81
Poll the system theme in desktop (#3063)
m-sasha Jun 26, 2026
545691b
Remove `foundation` dependency on skiko `SystemTheme` (#3160)
m-sasha Jun 26, 2026
0799f00
Set isClearFocusOnMouseDownEnabled to false by default (#3162)
m-sasha Jun 26, 2026
b74c2df
Increase swipe duration (#3161)
svastven Jun 26, 2026
2adbe7c
Fix issue of loading Compose scene inside ComposeHostingViewControlle…
ASalavei Jun 26, 2026
fa55d7a
[web] use css min for positioning backing input fields, calc is redun…
Schahen Jun 26, 2026
1c9cfe7
[web] Introduce separate test for composite input which invokes both …
Schahen Jun 29, 2026
6cdb45a
Implement `ComposeDesktopEntryPoint.captureContentToImage` (#3155)
m-sasha Jun 30, 2026
3df4bf6
Implement `SkikoComposeUiTest.runWithoutImplicitWait` (#3168)
m-sasha Jun 30, 2026
0f952f2
Prevent `NavigationDrawer` drags during swipe-back (#3165)
svastven Jul 1, 2026
6e33c7d
(script) Copy settings.gradle
igordmn Jun 29, 2026
25dd987
(script) Copy build-fork.gradle for every project in fork-project/set…
igordmn Jun 29, 2026
b2b3e54
(script) Copy buildSrc-fork
igordmn Jun 29, 2026
5bed868
Fork pluginManagement and buildscript in settings.gradle
igordmn Jun 29, 2026
371c223
Use forked build files
igordmn Jun 29, 2026
08ffa9b
(script) copy libs.versions.toml
igordmn Jul 1, 2026
1a22833
Use libs-fork.versions.toml
igordmn Jul 1, 2026
bf31387
Fix buildSrc paths in settings-fork.gradle (#3174)
igordmn Jul 1, 2026
997e244
Fix frame drops when dragging scrollable content (#3171)
ASalavei Jul 2, 2026
20569b5
Update skiko to 0.150.1 (#3178)
hub-bla Jul 2, 2026
158e65e
CoreTextField: Trigger relayout when stale fonts are detected in meas…
terrakok Jul 2, 2026
7ae39c9
Add iOS instrumented tests run configuration script (#3173)
svastven Jul 3, 2026
0b0759c
Update skiko to 0.150.1 in the new libs-fork.versions.toml (#3185)
hub-bla Jul 3, 2026
1c86b9a
buildSrc-fork. Fork more files (#3186)
igordmn Jul 6, 2026
9d98832
buildSrc-fork. Remove unused build code. Remove plugins (#3187)
igordmn Jul 6, 2026
7542c5e
Run `GlobalSnapshotManager` on `trampolineDispatcher` (#3175)
MatkovIvan Jul 6, 2026
cfa57dc
Do not rely on offscreen layer for outsets handling (#3191)
MatkovIvan Jul 7, 2026
60cab5f
Update back gesture layout direction handling on iOS (#3188)
svastven Jul 7, 2026
4648f4e
Add SelectionContainer iOS instrumented tests (#3113)
janinadavydova Jul 7, 2026
4802b3b
[demo] Update Selection example to toggle the isSelectionAutoScrollEn…
Schahen Jul 7, 2026
77724b3
Fix new line detection in `TextInputHelpers` loop logic for iOS (#3197)
mazunin-v-jb Jul 7, 2026
96134b0
[demo] Introduce isFromHardwareSource - synced label to the BasicText…
Schahen Jul 7, 2026
a042eab
Update skiko to `0.151.0-alpha01` (#3204)
MatkovIvan Jul 8, 2026
07c508b
Convert UIKit keyboard animation curve to UIViewAnimationOptions (#3183)
Kyle-Ye Jul 8, 2026
6618df7
Remove pre-iOS 14 compatibility branches (#3180)
svastven Jul 8, 2026
e99a7f3
Update wasm Demo run configuration settings (#3093)
ApoloApps Jul 9, 2026
92f811f
Add PrefetchScheduler for Web Platforms (#2928)
ApoloApps Jul 9, 2026
713a8e2
Prevent recursive frame rendering in ComposeSceneMediator (#3206)
ASalavei Jul 9, 2026
c196ebe
Migrate to the new skiko web runtime publication (#3210)
terrakok Jul 10, 2026
6c758c5
Add isAlive checks to access accessibility node data (#3205)
ASalavei Jul 10, 2026
3ab5858
Fix `CAFrameRateRangeDefault` unavailable on iOS 14 (#3207)
svastven Jul 13, 2026
dc21c06
Window Insets support for Compose for Web (#3202)
terrakok Jul 13, 2026
84023cf
Use single skiko-awt-runtime-all fat jar dependency on Desktop (#3198)
hub-bla Jul 13, 2026
facc274
Support OutOfFrameExecutor in Web platform (#2929)
ApoloApps Jul 13, 2026
ee871c6
Fix iOS text field focus transfer across scenes (#3203)
Kyle-Ye Jul 13, 2026
145268a
Fix a11y root element having 0×0 dimensions on web (#3035)
spookyvert Jul 13, 2026
7036ba6
Fix a regression in scrolling when ComposeViewport is embedded in HTM…
eymar Jul 13, 2026
ee91968
Fix dropped edge taps on iOS (#3209)
svastven Jul 13, 2026
82f4310
Add WebGL2 support check to ComposeWindow for improved error handling…
eymar Jul 13, 2026
2380572
[web] backing fields for inputs are actually contenteditable dom and …
Schahen Jul 13, 2026
6e43138
Add swipe back tests (#3176)
svastven Jul 13, 2026
3dbdf9a
Make web demo full screen and add a loading indicator (#3225)
eymar Jul 14, 2026
bb16f00
Use didMoveToWindow callback to start CMPViewController lifecycle (#3…
ASalavei Jul 14, 2026
605c93b
Ensure floating cursor stays within text layout bounds on iOS (#3224)
gavr123456789 Jul 15, 2026
567f7a6
Call preventDefault on touch events when Compose consumed correspondi…
eymar Jul 15, 2026
c6af05e
Update demo project to use separate skiko-skottie dependencies (#3234)
hub-bla Jul 15, 2026
ca8c16f
[web] Reuse same mediaQuery listener logic both for resize and theme …
Schahen Jul 16, 2026
6631afc
Configure karma to wait for skiko.wasm initialization before running …
eymar Jul 16, 2026
4cce5cf
Remove `ComposeUiFlags.useLegacyRenderNodeLayers` flag (#3213)
MatkovIvan Jul 20, 2026
b07ce24
UI - optimize object allocations (#3164)
ApoloApps Jul 20, 2026
d65f0eb
Adds CanvasHolder class to avoid creating a new SkiaBackedCanvas obje…
ApoloApps Jun 11, 2026
5ebe3d6
Change comment mentioning Android Canvas
ApoloApps Jun 16, 2026
a864797
Update ComposeUiTest.skiko.kt after rebase on top of jb-main
ApoloApps Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ abstract class DesktopGraphicsTest {
protected fun initCanvas(widthPx: Int, heightPx: Int): Canvas {
require(_surface == null)
_surface = Surface.makeRasterN32Premul(widthPx, heightPx)
return SkiaBackedCanvas(_surface!!.canvas)
return _surface!!.canvas.asComposeCanvas()
}

@After
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.jetbrains.skia.Matrix44
import org.jetbrains.skia.MipmapMode
import org.jetbrains.skia.Paint as SkPaint
import org.jetbrains.skia.SamplingMode
import org.jetbrains.skia.Surface
import org.jetbrains.skia.impl.use

@Deprecated(
Expand All @@ -46,13 +47,15 @@ internal actual fun ActualCanvas(image: ImageBitmap): Canvas {
require(!skiaBitmap.isImmutable) {
"Cannot draw on immutable ImageBitmap"
}
return SkiaBackedCanvas(SkCanvas(skiaBitmap))
return SkiaBackedCanvas().apply {
internalSkiaCanvas = SkCanvas(skiaBitmap)
}
}

/**
* Convert the [org.jetbrains.skia.Canvas] instance into a Compose-compatible Canvas
*/
fun SkCanvas.asComposeCanvas(): Canvas = SkiaBackedCanvas(this)
fun SkCanvas.asComposeCanvas(): Canvas = SkiaBackedCanvas().apply { internalSkiaCanvas = this@asComposeCanvas }

/**
* Provides access to the underlying [org.jetbrains.skia.Canvas] instance.
Expand All @@ -75,6 +78,26 @@ val Canvas.skiaCanvas: SkCanvas
val Canvas.nativeCanvas: NativeCanvas
get() = skiaCanvas


// Stub canvas instance used to keep the internal canvas parameter non-null during its
// scoped usage and prevent unnecessary byte code null checks from being generated
private val EmptyCanvas = Surface.makeNull(1,1).canvas

/**
* Holder class that is used to issue scoped calls to a [Canvas] from the framework equivalent
* canvas without having to allocate an object on each draw call
*/
class CanvasHolder {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: a new public-stable API that we'll have to maintain forever

@PublishedApi internal val skiaBackedCanvas = SkiaBackedCanvas()

inline fun drawInto(targetCanvas: SkCanvas, block: Canvas.() -> Unit) {
val previousCanvas = skiaBackedCanvas.internalSkiaCanvas
skiaBackedCanvas.internalSkiaCanvas = targetCanvas
skiaBackedCanvas.block()
skiaBackedCanvas.internalSkiaCanvas = previousCanvas
}
}

// This was added for internal usage from old render layers (another submodule),
// but wasn't properly marked as internal. Keep it as deprecated for some time to be safe.
@InternalComposeApi
Expand All @@ -86,9 +109,12 @@ var Canvas.alphaMultiplier: Float
get() = (this as SkiaBackedCanvas).alphaMultiplier
set(value) { (this as SkiaBackedCanvas).alphaMultiplier = value }

internal class SkiaBackedCanvas(
internal val internalSkiaCanvas: SkCanvas,
) : Canvas {
@PublishedApi
internal class SkiaBackedCanvas : Canvas {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't supposed to be exposed. Again, requirement for binary compatibility in a place where we're not ready to do it


// Keep the internal canvas as a var prevent having to allocate an AndroidCanvas
// instance on each draw call
@PublishedApi internal var internalSkiaCanvas: SkCanvas = EmptyCanvas
internal var alphaMultiplier: Float = 1.0f

private fun Paint.asSkiaPaintWithAppliedAlphaMultiplier(): SkPaint {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.ui.InternalComposeUiApi
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Path as SkPath
import org.jetbrains.skia.PathDirection
import org.jetbrains.skia.PathBuilder
Expand Down Expand Up @@ -89,6 +90,11 @@ internal class SkiaBackedPath(
*/
internal var isSkiaPathObserved = false

// Temporary value holders to reuse an object (not part of a state):
private var radii: FloatArray? = null

private var mMatrix: Matrix33? = null

private inline fun mutatePath(block: PathBuilder.() -> Unit) {
synchronizeBuilderIfNeeded()
pathBuilder.apply(block)
Expand Down Expand Up @@ -298,41 +304,30 @@ internal class SkiaBackedPath(
level = DeprecationLevel.HIDDEN
)
override fun addRoundRect(roundRect: RoundRect) = mutatePath {
addRRect(
roundRect.left,
roundRect.top,
roundRect.right,
roundRect.bottom,
floatArrayOf(
roundRect.topLeftCornerRadius.x,
roundRect.topLeftCornerRadius.y,
roundRect.topRightCornerRadius.x,
roundRect.topRightCornerRadius.y,
roundRect.bottomRightCornerRadius.x,
roundRect.bottomRightCornerRadius.y,
roundRect.bottomLeftCornerRadius.x,
roundRect.bottomLeftCornerRadius.y
),
PathDirection.COUNTER_CLOCKWISE
)
addRoundRect(roundRect)
}

override fun addRoundRect(roundRect: RoundRect, direction: Path.Direction) = mutatePath {
if (radii == null) radii = FloatArray(8)
with(radii!!) {
this[0] = roundRect.topLeftCornerRadius.x
this[1] = roundRect.topLeftCornerRadius.y

this[2] = roundRect.topRightCornerRadius.x
this[3] = roundRect.topRightCornerRadius.y

this[4] = roundRect.bottomRightCornerRadius.x
this[5] = roundRect.bottomRightCornerRadius.y

this[6] = roundRect.bottomLeftCornerRadius.x
this[7] = roundRect.bottomLeftCornerRadius.y
}
addRRect(
roundRect.left,
roundRect.top,
roundRect.right,
roundRect.bottom,
floatArrayOf(
roundRect.topLeftCornerRadius.x,
roundRect.topLeftCornerRadius.y,
roundRect.topRightCornerRadius.x,
roundRect.topRightCornerRadius.y,
roundRect.bottomRightCornerRadius.x,
roundRect.bottomRightCornerRadius.y,
roundRect.bottomLeftCornerRadius.x,
roundRect.bottomLeftCornerRadius.y
),
radii!!,
direction.toSkiaPathDirection()
)
}
Expand Down Expand Up @@ -372,7 +367,9 @@ internal class SkiaBackedPath(
}

override fun transform(matrix: Matrix) = mutatePath {
transform(identityMatrix33().apply { setFrom(matrix) })
if (mMatrix == null) mMatrix = identityMatrix33()
mMatrix!!.setFrom(matrix)
transform(mMatrix!!)
}

override fun getBounds(): Rect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ private fun List<Color>.toColor4fArray(): Array<Color4f> =
Color4f(color.red, color.green, color.blue, color.alpha)
}

private fun List<Float>.toFloatArray(): FloatArray = FloatArray(size) { i -> this[i] }

private fun validateColorStops(colors: List<Color>, colorStops: List<Float>?) {
if (colorStops == null) {
if (colors.size < 2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.isUnspecified
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.CanvasHolder
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.RenderEffect
import androidx.compose.ui.graphics.SkiaBackedCanvas
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.graphics.asSkiaColorFilter
import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
Expand Down Expand Up @@ -70,6 +70,8 @@ actual class GraphicsLayer internal constructor(
private var parentLayerUsages = 0
private val childDependenciesTracker = ChildLayerDependenciesTracker()

private val canvasHolder : CanvasHolder = CanvasHolder()

actual var compositingStrategy: CompositingStrategy = CompositingStrategy.Auto
set(value) {
if (field != value) {
Expand Down Expand Up @@ -337,10 +339,11 @@ actual class GraphicsLayer internal constructor(
val renderNode = renderNode ?: return
val recordingCanvas = renderNode.beginRecording()
try {
val composeCanvas = recordingCanvas.asComposeCanvas() as SkiaBackedCanvas
childDependenciesTracker.withTracking(
onDependencyRemoved = { it.onRemovedFromParentLayer() },
) { block(composeCanvas) }
canvasHolder.drawInto(recordingCanvas) {
childDependenciesTracker.withTracking(
onDependencyRemoved = { it.onRemovedFromParentLayer() },
) { block(this@drawInto as SkiaBackedCanvas) }
}
} finally {
renderNode.endRecording()
}
Expand Down Expand Up @@ -368,6 +371,9 @@ actual class GraphicsLayer internal constructor(
discardContentIfReleasedAndHaveNoParentLayerUsages()
}

// Temporary value holders to reuse an object (not part of a state):
private var radii: FloatArray? = null

@OptIn(InternalComposeUiApi::class)
private fun configureOutlineAndClip() {
if (!outlineDirty) return
Expand All @@ -386,23 +392,30 @@ actual class GraphicsLayer internal constructor(
tmpOutline.rect.bottom,
antiAlias = true
)
is Outline.Rounded -> renderNode.setClipRRect(
tmpOutline.roundRect.left,
tmpOutline.roundRect.top,
tmpOutline.roundRect.right,
tmpOutline.roundRect.bottom,
floatArrayOf(
tmpOutline.roundRect.topLeftCornerRadius.x,
tmpOutline.roundRect.topLeftCornerRadius.y,
tmpOutline.roundRect.topRightCornerRadius.x,
tmpOutline.roundRect.topRightCornerRadius.y,
tmpOutline.roundRect.bottomRightCornerRadius.x,
tmpOutline.roundRect.bottomRightCornerRadius.y,
tmpOutline.roundRect.bottomLeftCornerRadius.x,
tmpOutline.roundRect.bottomLeftCornerRadius.y
),
antiAlias = true
)
is Outline.Rounded -> {
if (radii == null) radii = FloatArray(8)
with(radii!!) {
this[0] = tmpOutline.roundRect.topLeftCornerRadius.x
this[1] = tmpOutline.roundRect.topLeftCornerRadius.y

this[2] = tmpOutline.roundRect.topRightCornerRadius.x
this[3] = tmpOutline.roundRect.topRightCornerRadius.y

this[4] = tmpOutline.roundRect.bottomRightCornerRadius.x
this[5] = tmpOutline.roundRect.bottomRightCornerRadius.y

this[6] = tmpOutline.roundRect.bottomLeftCornerRadius.x
this[7] = tmpOutline.roundRect.bottomLeftCornerRadius.y
}
renderNode.setClipRRect(
tmpOutline.roundRect.left,
tmpOutline.roundRect.top,
tmpOutline.roundRect.right,
tmpOutline.roundRect.bottom,
radii!!,
antiAlias = true
)
}
is Outline.Generic -> renderNode.setClipPath(tmpOutline.path.materializeSkiaPath(), antiAlias = true)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import androidx.compose.ui.InternalComposeUiApi
import androidx.compose.ui.draganddrop.DragAndDropTransferData
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.CanvasHolder
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.node.RootForTest
Expand Down Expand Up @@ -227,6 +227,9 @@ open class SkikoComposeUiTest @InternalTestApi constructor(
)

private val surface = Surface.makeRasterN32Premul(width, height)

private val canvasHolder : CanvasHolder = CanvasHolder()

private val size = IntSize(width, height)

@InternalComposeUiApi
Expand Down Expand Up @@ -322,9 +325,10 @@ open class SkikoComposeUiTest @InternalTestApi constructor(
*/
private fun redraw() = runOnUiThread {
scene.measureAndLayout()
with(surface.canvas) {
clear(Color.TRANSPARENT)
scene.draw(asComposeCanvas())
val skCanvas = surface.canvas
skCanvas.clear(Color.TRANSPARENT)
canvasHolder.drawInto(skCanvas) {
scene.draw(this)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.CanvasHolder
import androidx.compose.ui.input.InputModeManager
import androidx.compose.ui.input.key.KeyEvent as ComposeKeyEvent
import androidx.compose.ui.input.key.internal
Expand Down Expand Up @@ -182,6 +183,8 @@ internal class ComposeSceneMediator(
val windowHandle by skiaLayerComponent::windowHandle
val renderApi by skiaLayerComponent::renderApi
val semanticsOwners: Collection<SemanticsOwner> by semanticsOwnerManager::semanticsOwners

private val canvasHolder: CanvasHolder = CanvasHolder()

/**
* @see ComposeFeatureFlags.useInteropBlending
Expand Down Expand Up @@ -727,13 +730,13 @@ internal class ComposeSceneMediator(
interopContainer.postponingExecutingScheduledUpdates {
canvas.withSceneOffset {
with(sceneRenderingScope) {
scene.render(frameRecomposer, asComposeCanvas(), nanoTime)
scene.render(frameRecomposer, this@withSceneOffset, nanoTime)
}
}
}
}

private inline fun SkCanvas.withSceneOffset(crossinline block: SkCanvas.() -> Unit) {
private inline fun SkCanvas.withSceneOffset(crossinline block: Canvas.() -> Unit) {
// Offset of scene relative to [container]
val sceneBoundsOffset = sceneBoundsInPx?.topLeft ?: Offset.Zero
// Offset of canvas relative to [container]
Expand All @@ -744,7 +747,7 @@ internal class ComposeSceneMediator(
val sceneOffset = sceneBoundsOffset - contentOffset
save()
translate(sceneOffset.x, sceneOffset.y)
block()
canvasHolder.drawInto(this, block)
restore()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.LocalSystemTheme
import androidx.compose.ui.SystemTheme
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.graphics.CanvasHolder
import androidx.compose.ui.navigationevent.UIKitNavigationEventInput
import androidx.compose.ui.platform.DefaultArchitectureComponentsOwner
import androidx.compose.ui.platform.FrameRecomposer
Expand Down Expand Up @@ -120,6 +120,7 @@ internal class ComposeContainer(
private val systemThemeState: MutableState<SystemTheme> = mutableStateOf(SystemTheme.Unknown)

private val focusedViewsList = FocusedViewsList()
private val canvasHolder = CanvasHolder()

init {
if (configuration.enforceStrictPlistSanityCheck) {
Expand Down Expand Up @@ -205,7 +206,9 @@ internal class ComposeContainer(
},
useSeparateRenderThreadWhenPossible = configuration.parallelRendering,
render = { canvas, nanoTime ->
mediator?.render(canvas.asComposeCanvas(), nanoTime)
canvasHolder.drawInto(canvas) {
mediator?.render(this, nanoTime)
}
}
)
metalView.canBeOpaque = configuration.opaque
Expand Down
Loading