Skip to content

Instantly share code, notes, and snippets.

@colinrtwhite
Last active November 13, 2023 13:41
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save colinrtwhite/c2966e0b8584b4cdf0a5b05786b20ae1 to your computer and use it in GitHub Desktop.
Save colinrtwhite/c2966e0b8584b4cdf0a5b05786b20ae1 to your computer and use it in GitHub Desktop.
A painter that wraps another painter to overwrite its color filter, alpha, and/or onDraw.
/**
* Create and return a new [Painter] that wraps [painter] with its [alpha], [colorFilter], or [onDraw] overwritten.
*/
fun forwardingPainter(
painter: Painter,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null,
onDraw: DrawScope.(ForwardingDrawInfo) -> Unit = DefaultOnDraw,
): Painter = ForwardingPainter(painter, alpha, colorFilter, onDraw)
data class ForwardingDrawInfo(
val painter: Painter,
val alpha: Float,
val colorFilter: ColorFilter?,
)
private class ForwardingPainter(
private val painter: Painter,
private var alpha: Float,
private var colorFilter: ColorFilter?,
private val onDraw: DrawScope.(ForwardingDrawInfo) -> Unit,
) : Painter() {
private var info = newInfo()
override val intrinsicSize get() = painter.intrinsicSize
override fun applyAlpha(alpha: Float): Boolean {
if (alpha != DefaultAlpha) {
this.alpha = alpha
this.info = newInfo()
}
return true
}
override fun applyColorFilter(colorFilter: ColorFilter?): Boolean {
if (colorFilter != null) {
this.colorFilter = colorFilter
this.info = newInfo()
}
return true
}
override fun DrawScope.onDraw() = onDraw(info)
private fun newInfo() = ForwardingDrawInfo(painter, alpha, colorFilter)
}
private val DefaultOnDraw: DrawScope.(ForwardingDrawInfo) -> Unit = { info ->
with(info.painter) {
draw(size, info.alpha, info.colorFilter)
}
}
@jasco
Copy link

jasco commented May 25, 2022

As of revision 3, I notice that applyAlpha and applyColorFilter have conditionals that currently only apply the changes if the passed parameter is set to the default. I do not immediately see why a default checking guard is needed, but in any event I'm thinking that it was intended to be checking that the original value was still defaulted, so this.alpha == DefaultAlpha and this.colorFilter == null respectively. I wonder if the guard might be further improved by looking for a change instead, this.alpha != alpha and this.colorFilter != colorFilter? (Also the return values might be updated to reflect whether the value was applied.) Thanks for posting this.

@desgraci
Copy link

    override fun applyAlpha(alpha: Float): Boolean {
        if (alpha == DefaultAlpha) {
            this.alpha = alpha
            this.info = newInfo()
        }
        return true
    }
    ...
override fun applyColorFilter(colorFilter: ColorFilter?): Boolean {
        if (colorFilter == null) {
            this.colorFilter = colorFilter
            this.info = newInfo()
        }
        return true
    }

May I ask, why is always setting null and the DefaultAlpha?

@colinrtwhite
Copy link
Author

@desgraci That was a typo! Updated the gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment