Unverified Commit f5b0a10d authored by ApoloApps's avatar ApoloApps Committed by GitHub

Transform Matrix* to value classes (#1205)

It transforms Matrix* classes to be value classes so that we avoid
double allocation in these simple classes (1 fo FloatArray and 1 for the
Matrix class itself)
https://github.com/JetBrains/skiko/pull/1137 followup (at least partly)

Fixes
[SKIKO-1140](https://youtrack.jetbrains.com/issue/SKIKO-1140/Change-Matrix-to-value-classes)

**Next**
Follow-up PR in Compose Core to make use of the internal float array
constructor to reuse if coming from another FLoatArray

---------
Co-authored-by: 's avatarIvan Matkov <matkov.ivan@gmail.com>
parent 59642ebe
......@@ -3,31 +3,32 @@ package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.InteropScope
import org.jetbrains.skia.impl.withResult
import kotlin.jvm.JvmInline
/**
* 2x2 matrix.
* @param mat 4 elements in row-major order
*/
class Matrix22(vararg mat: Float) {
@JvmInline
value class Matrix22 internal constructor(val mat: FloatArray) {
constructor(
m00: Float, m01: Float,
m10: Float, m11: Float
) : this(
floatArrayOf(
m00, m01,
m10, m11
)
)
/**
* Matrix elements are in row-major order.
* The constructor parameters are in row-major order.
*/
val mat: FloatArray
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Matrix22) return false
return mat.contentEquals(other.mat)
}
override fun hashCode(): Int {
val PRIME = 59
var result = 1
result = result * PRIME + mat.contentHashCode()
return result
init {
require(mat.size == 4) { "Expected 4 elements, got ${mat.size}" }
}
override fun toString(): String {
return "Matrix22(_mat=$mat)"
return "Matrix22(mat=${mat.contentToString()})"
}
companion object {
......@@ -35,15 +36,7 @@ class Matrix22(vararg mat: Float) {
internal fun fromInteropPointer(block: InteropScope.(InteropPointer) -> Unit): Matrix22 {
val result = withResult(FloatArray(4), block)
return Matrix22(*result)
return Matrix22(result)
}
}
/**
* The constructor parameters are in row-major order.
*/
init {
require(mat.size == 4) { "Expected 4 elements, got ${mat.size}" }
this.mat = mat
}
}
package org.jetbrains.skia
import kotlin.jvm.JvmInline
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
internal fun Float.toRadians(): Double = this.toDouble() / 180 * PI
private const val radiansToDegrees = 180.0 / PI
private const val tolerance = (1.0f / (1 shl 12)).toDouble()
internal inline fun Float.toRadians(): Double = this.toDouble() * radiansToDegrees
/**
*
......@@ -16,21 +19,35 @@ internal fun Float.toRadians(): Double = this.toDouble() / 180 * PI
*
* Matrix includes a hidden variable that classifies the type of matrix to
* improve performance. Matrix is not thread safe unless getType() is called first.
*
* @param mat 9-element array of floats representing the matrix in row-major order
*
* <pre>`
* | scaleX skewX transX |
* | skewY scaleY transY |
* | persp0 persp1 persp2 |
`</pre> *
*
* @see [https://fiddle.skia.org/c/@Matrix_063](https://fiddle.skia.org/c/@Matrix_063)
*/
class Matrix33(vararg mat: Float) {
/**
*
* Matrix33 elements are in row-major order.
*
* <pre>`
* | scaleX skewX transX |
* | skewY scaleY transY |
* | persp0 persp1 persp2 |
`</pre> *
*/
val mat: FloatArray
@JvmInline
value class Matrix33 internal constructor(val mat: FloatArray) {
constructor(
m00: Float, m01: Float, m02: Float,
m10: Float, m11: Float, m12: Float,
m20: Float, m21: Float, m22: Float,
) : this(
floatArrayOf(
m00, m01, m02,
m10, m11, m12,
m20, m21, m22,
)
)
init {
require(mat.size == 9) { "Expected 9 elements, got ${mat.size}" }
}
fun makePreScale(sx: Float, sy: Float): Matrix33 {
return Matrix33(
mat[0] * sx,
......@@ -100,21 +117,8 @@ class Matrix33(vararg mat: Float) {
return Matrix44(mat[0], mat[1], 0f, mat[2], mat[3], mat[4], 0f, mat[5], 0f, 0f, 1f, 0f, mat[6], mat[7], 0f, mat[8])
}
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Matrix33) return false
return mat.contentEquals(other.mat)
}
override fun hashCode(): Int {
val PRIME = 59
var result = 1
result = result * PRIME + mat.contentHashCode()
return result
}
override fun toString(): String {
return "Matrix33(_mat=$mat)"
return "Matrix33(mat=${mat.contentToString()})"
}
companion object {
......@@ -192,7 +196,7 @@ class Matrix33(vararg mat: Float) {
val rad = deg.toRadians()
var sin = sin(rad)
var cos = cos(rad)
val tolerance = (1.0f / (1 shl 12)).toDouble()
val tolerance = tolerance
if (abs(sin) <= tolerance) sin = 0.0
if (abs(cos) <= tolerance) cos = 0.0
return Matrix33(
......@@ -231,7 +235,7 @@ class Matrix33(vararg mat: Float) {
val rad = deg.toRadians()
var sin = sin(rad)
var cos = cos(rad)
val tolerance = (1.0f / (1 shl 12)).toDouble()
val tolerance = tolerance
if (abs(sin) <= tolerance) sin = 0.0
if (abs(cos) <= tolerance) cos = 0.0
return Matrix33(
......@@ -265,9 +269,4 @@ class Matrix33(vararg mat: Float) {
return Matrix33(1f, sx, 0f, sy, 1f, 0f, 0f, 0f, 1f)
}
}
init {
require(mat.size == 9) { "Expected 9 elements, got ${mat.size}" }
this.mat = mat
}
}
......@@ -3,6 +3,7 @@ package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.InteropScope
import org.jetbrains.skia.impl.withResult
import kotlin.jvm.JvmInline
/**
*
......@@ -12,13 +13,30 @@ import org.jetbrains.skia.impl.withResult
* +X goes to the right
* +Y goes down
* +Z goes into the screen (away from the viewer)
*
* @param mat 16 elements in row-major order
*/
class Matrix44(vararg mat: Float) {
@JvmInline
value class Matrix44 internal constructor(val mat: FloatArray) {
constructor(
m00: Float, m01: Float, m02: Float, m03: Float,
m10: Float, m11: Float, m12: Float, m13: Float,
m20: Float, m21: Float, m22: Float, m23: Float,
m30: Float, m31: Float, m32: Float, m33: Float
) : this(
floatArrayOf(
m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m32, m33,
)
)
/**
* Matrix elements are in row-major order.
* The constructor parameters are in row-major order.
*/
val mat: FloatArray
init {
require(mat.size == 16) { "Expected 16 elements, got ${mat.size}" }
}
/**
*
* When converting from Matrix44 to Matrix33, the third row and
......@@ -35,21 +53,8 @@ class Matrix44(vararg mat: Float) {
return Matrix33(mat[0], mat[1], mat[3], mat[4], mat[5], mat[7], mat[12], mat[13], mat[15])
}
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Matrix44) return false
return mat.contentEquals(other.mat)
}
override fun hashCode(): Int {
val PRIME = 59
var result = 1
result = result * PRIME + mat.contentHashCode()
return result
}
override fun toString(): String {
return "Matrix44(_mat=$mat)"
return "Matrix44(mat=${mat.contentToString()})"
}
companion object {
......@@ -57,15 +62,7 @@ class Matrix44(vararg mat: Float) {
internal fun fromInteropPointer(block: InteropScope.(InteropPointer) -> Unit): Matrix44 {
val result = withResult(FloatArray(16), block)
return Matrix44(*result)
return Matrix44(result)
}
}
/**
* The constructor parameters are in row-major order.
*/
init {
require(mat.size == 16) { "Expected 16 elements, got ${mat.size}" }
this.mat = mat
}
}
......@@ -145,17 +145,7 @@ class PathMeasure internal constructor(ptr: NativePointer) : Managed(ptr, _Final
withNullableResult(FloatArray(9)) {
_nGetMatrix(_ptr, distance, getPosition, getTangent, it)
}?.let { data ->
Matrix33(
data[0],
data[1],
data[2],
data[3],
data[4],
data[5],
data[6],
data[7],
data[8]
)
Matrix33(data)
}
} finally {
reachabilityBarrier(this)
......
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