commonMain.me.saket.telephoto.zoomable.internal.dimens.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zoomable-desktop Show documentation
Show all versions of zoomable-desktop Show documentation
A Modifier for making anything zoomable.
The newest version!
package me.saket.telephoto.zoomable.internal
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.isFinite
import androidx.compose.ui.geometry.isSpecified
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.layout.ScaleFactor
import androidx.compose.ui.layout.times
import androidx.compose.ui.unit.IntSize
import me.saket.telephoto.zoomable.BaseZoomFactor
import me.saket.telephoto.zoomable.ContentZoomFactor
import me.saket.telephoto.zoomable.UserZoomFactor
import kotlin.math.roundToInt
internal fun Size.roundToIntSize() =
IntSize(width.roundToInt(), height.roundToInt())
internal fun Size.discardFractionalParts(): IntSize {
return IntSize(width = width.toInt(), height = height.toInt())
}
internal val Size.isSpecifiedAndNonEmpty: Boolean
get() = isSpecified && !isEmpty()
internal val ScaleFactor.maxScale: Float
get() = maxOf(scaleX, scaleY)
internal val ScaleFactor.minScale: Float
get() = minOf(scaleX, scaleY)
internal operator fun ScaleFactor.unaryMinus(): ScaleFactor =
this * -1f
internal val ScaleFactor.Companion.Zero
get() = ScaleFactor(0f, 0f)
internal fun ScaleFactor.isPositiveAndFinite(): Boolean {
return scaleX.isPositiveAndFinite() && scaleY.isPositiveAndFinite()
}
internal fun Offset.isSpecifiedAndFinite(): Boolean {
return isSpecified && isFinite
}
internal fun Float.isPositiveAndFinite(): Boolean {
return this.isFinite() && this >= 0f
}
internal val TransformOrigin.Companion.Zero
get() = TransformOrigin(0f, 0f)
internal operator fun Offset.times(factor: ScaleFactor) =
Offset(x = x * factor.scaleX, y = y * factor.scaleY)
internal operator fun Offset.div(factor: ScaleFactor) =
Offset(x = x / factor.scaleX, y = y / factor.scaleY)
internal operator fun Offset.div(zoom: ContentZoomFactor): Offset =
div(zoom.finalZoom())
internal operator fun Offset.times(zoom: ContentZoomFactor): Offset =
times(zoom.finalZoom())
internal operator fun Size.times(zoom: ContentZoomFactor): Size =
times(zoom.finalZoom())
internal operator fun UserZoomFactor.times(operand: Float): UserZoomFactor =
UserZoomFactor(value.times(operand))
internal operator fun BaseZoomFactor.times(factor: UserZoomFactor): ScaleFactor =
value.times(factor.value)
internal operator fun UserZoomFactor.minus(other: UserZoomFactor): UserZoomFactor {
return UserZoomFactor(value = value - other.value)
}
internal operator fun UserZoomFactor.div(other: UserZoomFactor): UserZoomFactor {
return UserZoomFactor(value = value / other.value)
}
internal fun UserZoomFactor.coerceIn(minimumValue: UserZoomFactor, maximumValue: UserZoomFactor): UserZoomFactor {
return UserZoomFactor(value = value.coerceIn(minimumValue.value, maximumValue.value))
}
/**
* Call [action] with [zoom] and [translate] applied to this offset. The value
* generated by [action] is returned by applying the inverse of [translate] and [zoom].
*
* The name of this function was inspired from [DrawScope.withTransform].
*/
internal fun Offset.withZoomAndTranslate(
zoom: ScaleFactor,
translate: Offset,
action: (Offset) -> Offset,
): Offset {
return (action((this * zoom) + translate) - translate) / zoom
}
internal fun Offset.withZoom(
zoom: ScaleFactor,
action: (Offset) -> Offset,
): Offset {
return withZoomAndTranslate(zoom, Offset.Zero, action)
}
internal fun Rect.times(scale: ScaleFactor): Rect =
Rect(offset = topLeft * scale, size = size * scale)
internal fun Rect.withOrigin(origin: TransformOrigin, action: Rect.() -> Rect): Rect {
val pivot = Offset(
x = size.width * origin.pivotFractionX,
y = size.height * origin.pivotFractionY,
)
val atOrigin = this.translate(-pivot)
val newRect = atOrigin.action()
return newRect.translate(pivot)
}
internal fun Rect.scaledAndOffsetBy(scale: ScaleFactor, offset: Offset): Rect {
return Rect(
left = (left * scale.scaleX) + offset.x,
right = (right * scale.scaleX) + offset.x,
top = (top * scale.scaleY) + offset.y,
bottom = (bottom * scale.scaleY) + offset.y,
)
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy