diff --git a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Matrix.scala b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Matrix.scala index dfe48ccb..91fb8240 100644 --- a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Matrix.scala +++ b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Matrix.scala @@ -20,13 +20,17 @@ final case class Matrix(a: Double, b: Double, c: Double, d: Double, e: Double, f this.d * that.c + this.e * that.f + this.f ) + inline def applyX(x: Double, y: Double): Double = a * x + b * y + c * 1 + inline def applyX(x: Int, y: Int): Int = (a * x + b * y + c * 1).toInt + inline def applyY(x: Double, y: Double): Double = d * x + e * y + f * 1 + inline def applyY(x: Int, y: Int): Int = (d * x + e * y + f * 1).toInt + /** Applies the transformation to (x, y). */ def apply(x: Double, y: Double): (Double, Double) = - (a * x + b * y + c * 1, d * x + e * y + f * 1) + (applyX(x, y), applyY(x, y)) /** Applies the transformation to (x, y). */ def apply(x: Int, y: Int): (Int, Int) = { - val res = apply(x.toDouble, y.toDouble) - (res._1.toInt, res._2.toInt) + (applyX(x, y), applyY(x, y)) } } diff --git a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Plane.scala b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Plane.scala index 247dd347..15d5fb84 100644 --- a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Plane.scala +++ b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/Plane.scala @@ -68,7 +68,7 @@ trait Plane extends Function2[Int, Int, Color] { outer => * @param cw clip width * @param ch clip height */ - final def clip(cx: Int, cy: Int, cw: Int, ch: Int): SurfaceView = + def clip(cx: Int, cy: Int, cw: Int, ch: Int): SurfaceView = if (cx == 0 && cy == 0) toSurfaceView(cw, ch) else new Plane { @@ -97,7 +97,7 @@ trait Plane extends Function2[Int, Int, Color] { outer => } /** Inverts a plane color. */ - def invertColor: Plane = map(_.invert) + final def invertColor: Plane = map(_.invert) /** Contramaps this plane using a matrix instead of a function. * @@ -124,32 +124,41 @@ trait Plane extends Function2[Int, Int, Color] { outer => Plane.MatrixPlane(matrix, this) /** Translates a plane. */ - def translate(dx: Double, dy: Double): Plane = contramapMatrix(Matrix(1, 0, -dx, 0, 1, -dy)) + final def translate(dx: Double, dy: Double): Plane = + if (dx == 0 && dy == 0) this + else contramapMatrix(Matrix(1, 0, -dx, 0, 1, -dy)) /** Flips a plane horizontally. */ - def flipH: Plane = contramapMatrix(Matrix(-1, 0, 0, 0, 1, 0)) + final def flipH: Plane = contramapMatrix(Matrix(-1, 0, 0, 0, 1, 0)) /** Flips a plane vertically. */ - def flipV: Plane = contramapMatrix(Matrix(1, 0, 0, 0, -1, 0)) + final def flipV: Plane = contramapMatrix(Matrix(1, 0, 0, 0, -1, 0)) /** Scales a plane. */ - def scale(sx: Double, sy: Double): Plane = contramapMatrix(Matrix(1.0 / sx, 0, 0, 0, 1.0 / sy, 0)) + final def scale(sx: Double, sy: Double): Plane = + if (sx == 1.0 && sy == 1.0) this + else contramapMatrix(Matrix(1.0 / sx, 0, 0, 0, 1.0 / sy, 0)) /** Scales a plane. */ - def scale(s: Double): Plane = scale(s, s) + final def scale(s: Double): Plane = scale(s, s) /** Rotates a plane by a certain angle (clockwise). */ - def rotate(theta: Double): Plane = { + final def rotate(theta: Double): Plane = { val ct = Math.cos(-theta) - val st = Math.sin(-theta) - contramapMatrix(Matrix(ct, -st, 0, st, ct, 0)) + if (ct == 1.0) this + else { + val st = Math.sin(-theta) + contramapMatrix(Matrix(ct, -st, 0, st, ct, 0)) + } } /** Shears a plane. */ - def shear(sx: Double, sy: Double): Plane = contramapMatrix(Matrix(1.0, -sx, 0, -sy, 1.0, 0)) + final def shear(sx: Double, sy: Double): Plane = + if (sx == 0.0 && sy == 0.0) this + else contramapMatrix(Matrix(1.0, -sx, 0, -sy, 1.0, 0)) /** Transposes a plane (switches the x and y coordinates). */ - def transpose: Plane = contramapMatrix(Matrix(0, 1, 0, 1, 0, 0)) + final def transpose: Plane = contramapMatrix(Matrix(0, 1, 0, 1, 0, 0)) /** Converts this plane to a surface view, assuming (0, 0) as the top-left corner. * @@ -171,12 +180,14 @@ trait Plane extends Function2[Int, Int, Color] { outer => object Plane { private[Plane] final case class MatrixPlane(matrix: Matrix, plane: Plane) extends Plane { def getPixel(x: Int, y: Int): Color = { - val (xx, yy) = matrix(x, y) - plane.getPixel(xx, yy) + plane.getPixel(matrix.applyX(x, y), matrix.applyY(x, y)) } override def contramapMatrix(matrix: Matrix) = MatrixPlane(this.matrix.multiply(matrix), plane) + + override def clip(cx: Int, cy: Int, cw: Int, ch: Int): SurfaceView = + translate(-cx, -cy).toSurfaceView(cw, ch) } /** Creates a plane from a constant color. diff --git a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/SurfaceView.scala b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/SurfaceView.scala index 128ed0d4..bea5eb8f 100644 --- a/core/shared/src/main/scala/eu/joaocosta/minart/graphics/SurfaceView.scala +++ b/core/shared/src/main/scala/eu/joaocosta/minart/graphics/SurfaceView.scala @@ -67,7 +67,7 @@ final case class SurfaceView(plane: Plane, width: Int, height: Int) extends Surf * @param x leftmost pixel on the destination plane * @param y topmost pixel on the destination plane */ - final def overlay(that: Surface, blendMode: BlendMode = BlendMode.Copy)(x: Int, y: Int): SurfaceView = + def overlay(that: Surface, blendMode: BlendMode = BlendMode.Copy)(x: Int, y: Int): SurfaceView = copy(plane = plane.overlay(that, blendMode)(x, y)) /** Inverts a surface color. */ @@ -90,7 +90,8 @@ final case class SurfaceView(plane: Plane, width: Int, height: Int) extends Surf /** Scales a surface. */ def scale(sx: Double, sy: Double): SurfaceView = - copy(plane = plane.scale(sx, sy), width = (width * sx).toInt, height = (height * sy).toInt) + if (sx == 1.0 && sy == 1.0) this + else copy(plane = plane.scale(sx, sy), width = (width * sx).toInt, height = (height * sy).toInt) /** Scales a surface. */ def scale(s: Double): SurfaceView = scale(s, s)