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; | ||
|  | 	} | ||
|  | } |