oleksandrbalan / pagecurl

This library allows to create an effect of turning pages, which can be used in book reader applications, custom on-boarding screens or elsewhere.
Apache License 2.0
303 stars 25 forks source link

Are there a plan to support compose multiplatform? #23

Closed fankes closed 8 months ago

fankes commented 11 months ago

Thank you for your project.

I took a look and saw that the drawing part is implemented using Android's own canvas.

Is it possible to use the canvas and imagebotmap provided by compose itself, so that multiplatform can be implemented, or there are alternatives on javaswing.

oleksandrbalan commented 11 months ago

I think it is definetelly possible to migrate to Compose multiplatform, the biggest issue would be to port shadow drawing. But it should be possible to make it work using expect&actual.

Currently I am focusing on another project, but I will try to look on it when I have some time.

And sorry for the late response.

fankes commented 11 months ago

Thank you for continuing to maintain this project.

Yes, I tried to transplant it myself, and the current problem does lie in shadow drawing. I have no way to solve it for the time being, because the skiko engine on the desktop platform does not have some useful development documents for me to read and refer to.

oleksandrbalan commented 11 months ago

Actually I am working a bit with shadows within that another project and this is how I simulate them on Android, Desktop and iOS targets:

common

import androidx.compose.ui.graphics.Paint

expect fun Paint.setBlurred(value: Float)

android

import android.graphics.BlurMaskFilter
import androidx.compose.ui.graphics.Paint

actual fun Paint.setBlurred(value: Float) {
    if (value == 0f) return
    asFrameworkPaint().maskFilter = BlurMaskFilter(value, BlurMaskFilter.Blur.NORMAL)
}

ios & jvm are the same:

import androidx.compose.ui.graphics.Paint
import org.jetbrains.skia.FilterBlurMode
import org.jetbrains.skia.MaskFilter

actual fun Paint.setBlurred(value: Float) {
    if (value == 0f) return
    asFrameworkPaint().maskFilter = MaskFilter.makeBlur(FilterBlurMode.NORMAL, value / 2f)
}

Note that "/ 2" is needed to normalize the shadow radius, as said in this article.

In the Skia library, the blurRadius value represents the standard deviation of the Gaussian distribution used for blurring. The blurring algorithm in Skia applies the blur effect symmetrically on both sides of the original shape. This means that a blurRadius value of r will result in a total blurring distance of 2r (i.e., r on each side).

usage

Modifier.drawWithCache {
    val paint = Paint().apply {
        setBlurred(blurRadius)
        color = Color.Black
    }

    onDrawWithContent {
        drawIntoCanvas { canvas ->
            canvas.drawPath(..., paint)
        }    
    }
}

Maybe you will find it useful for your solution 🤞

fankes commented 11 months ago

Thank you, I will try this solution.

fankes commented 10 months ago

Hi, I tried to supported this library to Jetpack Compose Multiplatform: https://github.com/fankes/pagecurl-multiplatform.

The good news is that I followed your approach to handling shadows and it basically works fine now.

But there are still some minor issues that have not been resolved yet, like the shadow offsets.

oleksandrbalan commented 10 months ago

Awesome, great job 👍