177 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
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;
 | 
						|
	}
 | 
						|
}
 |