LNXSDK/Kha/Sources/kha/Scaler.hx

177 lines
6.4 KiB
Haxe
Raw Normal View History

2025-01-22 16:18:30 +01:00
package kha;
import kha.math.FastMatrix3;
class TargetRectangle {
public var x: Float;
public var y: Float;
public var width: Float;
public var height: Float;
public var scaleFactor: Float;
public var rotation: ScreenRotation;
public inline function new(x: Float, y: Float, w: Float, h: Float, s: Float, r: ScreenRotation) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.scaleFactor = s;
this.rotation = r;
}
}
class Scaler {
public static function targetRect(width: Int, height: Int, destinationWidth: Int, destinationHeight: Int, rotation: ScreenRotation): TargetRectangle {
var scalex: Float;
var scaley: Float;
var scalew: Float;
var scaleh: Float;
var scale: Float;
switch (rotation) {
case ScreenRotation.RotationNone:
if (width / height > destinationWidth / destinationHeight) {
scale = destinationWidth / width;
scalew = width * scale;
scaleh = height * scale;
scalex = 0;
scaley = (destinationHeight - scaleh) * 0.5;
}
else {
scale = destinationHeight / height;
scalew = width * scale;
scaleh = height * scale;
scalex = (destinationWidth - scalew) * 0.5;
scaley = 0;
}
case ScreenRotation.Rotation90:
if (width / height > destinationHeight / destinationWidth) {
scale = destinationHeight / width;
scalew = width * scale;
scaleh = height * scale;
scalex = (destinationWidth - scaleh) * 0.5 + scaleh;
scaley = 0;
}
else {
scale = destinationWidth / height;
scalew = width * scale;
scaleh = height * scale;
scalex = 0 + scaleh;
scaley = (destinationHeight - scalew) * 0.5;
}
case ScreenRotation.Rotation180:
if (width / height > destinationWidth / destinationHeight) {
scale = destinationWidth / width;
scalew = width * scale;
scaleh = height * scale;
scalex = 0 + scalew;
scaley = (destinationHeight - scaleh) * 0.5 + scaleh;
}
else {
scale = destinationHeight / height;
scalew = width * scale;
scaleh = height * scale;
scalex = (destinationWidth - scalew) * 0.5 + scalew;
scaley = 0 + scaleh;
}
case ScreenRotation.Rotation270:
if (width / height > destinationHeight / destinationWidth) {
scale = destinationHeight / width;
scalew = width * scale;
scaleh = height * scale;
scalex = (destinationWidth - scaleh) * 0.5;
scaley = 0 + scalew;
}
else {
scale = destinationWidth / height;
scalew = width * scale;
scaleh = height * scale;
scalex = 0;
scaley = (destinationHeight - scalew) * 0.5 + scalew;
}
}
return new TargetRectangle(scalex, scaley, scalew, scaleh, scale, rotation);
}
public static function transformXDirectly(x: Int, y: Int, sourceWidth: Int, sourceHeight: Int, destinationWidth: Int, destinationHeight: Int,
rotation: ScreenRotation): Int {
var targetRect = targetRect(sourceWidth, sourceHeight, destinationWidth, destinationHeight, rotation);
switch (targetRect.rotation) {
case ScreenRotation.RotationNone:
return Std.int((x - targetRect.x) / targetRect.scaleFactor);
case ScreenRotation.Rotation90:
return Std.int((y - targetRect.y) / targetRect.scaleFactor);
case ScreenRotation.Rotation180:
return Std.int((targetRect.x - x) / targetRect.scaleFactor);
case ScreenRotation.Rotation270:
return Std.int((targetRect.y - y) / targetRect.scaleFactor);
}
}
/**
* Transform the X value from the given position in the source to a position in the destination canvas.
*
* @param x The X position.
* @param y The Y position.
* @param source The source image.
* @param destination The destination canvas.
* @param rotation The screen rotation.
*/
public static function transformX(x: Int, y: Int, source: Image, destination: Canvas, rotation: ScreenRotation): Int {
return transformXDirectly(x, y, source.width, source.height, destination.width, destination.height, rotation);
}
public static function transformYDirectly(x: Int, y: Int, sourceWidth: Int, sourceHeight: Int, destinationWidth: Int, destinationHeight: Int,
rotation: ScreenRotation): Int {
var targetRect = targetRect(sourceWidth, sourceHeight, destinationWidth, destinationHeight, rotation);
switch (targetRect.rotation) {
case ScreenRotation.RotationNone:
return Std.int((y - targetRect.y) / targetRect.scaleFactor);
case ScreenRotation.Rotation90:
return Std.int((targetRect.x - x) / targetRect.scaleFactor);
case ScreenRotation.Rotation180:
return Std.int((targetRect.y - y) / targetRect.scaleFactor);
case ScreenRotation.Rotation270:
return Std.int((x - targetRect.x) / targetRect.scaleFactor);
}
}
/**
* Transform the Y value from the given position in the source to a position in the destination canvas.
*
* @param x The X position.
* @param y The Y position.
* @param source The source image.
* @param destination The destination canvas.
* @param rotation The screen rotation.
*/
public static function transformY(x: Int, y: Int, source: Image, destination: Canvas, rotation: ScreenRotation): Int {
return transformYDirectly(x, y, source.width, source.height, destination.width, destination.height, rotation);
}
public static function scale(source: Image, destination: Canvas, rotation: ScreenRotation): Void {
var g = destination.g2;
g.pushTransformation(getScaledTransformation(source.width, source.height, destination.width, destination.height, rotation));
g.color = Color.White;
g.opacity = 1;
g.drawImage(source, 0, 0);
g.popTransformation();
}
public static function getScaledTransformation(width: Int, height: Int, destinationWidth: Int, destinationHeight: Int,
rotation: ScreenRotation): FastMatrix3 {
var rect = targetRect(width, height, destinationWidth, destinationHeight, rotation);
var sf = rect.scaleFactor;
var transformation = new FastMatrix3(sf, 0, rect.x, 0, sf, rect.y, 0, 0, 1);
switch (rotation) {
case RotationNone:
case Rotation90:
transformation = transformation.multmat(FastMatrix3.rotation(Math.PI / 2));
case Rotation180:
transformation = transformation.multmat(FastMatrix3.rotation(Math.PI));
case Rotation270:
transformation = transformation.multmat(FastMatrix3.rotation(Math.PI * 3 / 2));
}
return transformation;
}
}