265 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
package kha.js;
 | 
						|
 | 
						|
import kha.Color;
 | 
						|
import kha.graphics2.Graphics;
 | 
						|
import kha.graphics2.ImageScaleQuality;
 | 
						|
import kha.math.FastMatrix3;
 | 
						|
import js.html.CanvasRenderingContext2D;
 | 
						|
 | 
						|
class CanvasGraphics extends Graphics {
 | 
						|
	var canvas: CanvasRenderingContext2D;
 | 
						|
	var webfont: kha.js.Font;
 | 
						|
	var myColor: Color;
 | 
						|
	var scaleQuality: ImageScaleQuality;
 | 
						|
	var clipping: Bool = false;
 | 
						|
 | 
						|
	static var instance: CanvasGraphics;
 | 
						|
 | 
						|
	public function new(canvas: CanvasRenderingContext2D) {
 | 
						|
		super();
 | 
						|
		this.canvas = canvas;
 | 
						|
		instance = this;
 | 
						|
		myColor = Color.fromBytes(0, 0, 0);
 | 
						|
		// webfont = new Font("Arial", new FontStyle(false, false, false), 12);
 | 
						|
		// canvas.globalCompositeOperation = "normal";
 | 
						|
	}
 | 
						|
 | 
						|
	public static function stringWidth(font: kha.Font, text: String): Float {
 | 
						|
		if (instance == null)
 | 
						|
			return 5 * text.length;
 | 
						|
		else {
 | 
						|
			instance.font = font;
 | 
						|
			return instance.canvas.measureText(text).width;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	override public function begin(clear: Bool = true, clearColor: Color = null): Void {
 | 
						|
		if (clear)
 | 
						|
			this.clear(clearColor);
 | 
						|
	}
 | 
						|
 | 
						|
	override public function clear(color: Color = null): Void {
 | 
						|
		if (color == null)
 | 
						|
			color = 0x00000000;
 | 
						|
		canvas.strokeStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")";
 | 
						|
		canvas.fillStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")";
 | 
						|
		if (color.A == 0) // if color is transparent, clear the screen. Note: in Canvas, transparent colors will overlay, not overwrite.
 | 
						|
			canvas.clearRect(0, 0, canvas.canvas.width, canvas.canvas.height);
 | 
						|
		else
 | 
						|
			canvas.fillRect(0, 0, canvas.canvas.width, canvas.canvas.height);
 | 
						|
		this.color = myColor;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function end(): Void {}
 | 
						|
 | 
						|
	/*override public function translate(x: Float, y: Float) {
 | 
						|
		tx = x;
 | 
						|
		ty = y;
 | 
						|
	}*/
 | 
						|
	override public function drawImage(img: kha.Image, x: Float, y: Float) {
 | 
						|
		canvas.globalAlpha = opacity;
 | 
						|
		canvas.drawImage(cast(img, CanvasImage).image, x, y);
 | 
						|
		canvas.globalAlpha = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function drawScaledSubImage(image: kha.Image, sx: Float, sy: Float, sw: Float, sh: Float, dx: Float, dy: Float, dw: Float, dh: Float) {
 | 
						|
		canvas.globalAlpha = opacity;
 | 
						|
		try {
 | 
						|
			if (dw < 0 || dh < 0) {
 | 
						|
				canvas.save();
 | 
						|
				canvas.translate(dx, dy);
 | 
						|
				var x = 0.0;
 | 
						|
				var y = 0.0;
 | 
						|
				if (dw < 0) {
 | 
						|
					canvas.scale(-1, 1);
 | 
						|
					x = -dw;
 | 
						|
				}
 | 
						|
				if (dh < 0) {
 | 
						|
					canvas.scale(1, -1);
 | 
						|
					y = -dh;
 | 
						|
				}
 | 
						|
				canvas.drawImage(cast(image, CanvasImage).image, sx, sy, sw, sh, x, y, dw, dh);
 | 
						|
				canvas.restore();
 | 
						|
			}
 | 
						|
			else {
 | 
						|
				canvas.drawImage(cast(image, CanvasImage).image, sx, sy, sw, sh, dx, dy, dw, dh);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		catch (ex:Dynamic) {}
 | 
						|
		canvas.globalAlpha = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	override function set_color(color: Color): Color {
 | 
						|
		myColor = color;
 | 
						|
		canvas.strokeStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")";
 | 
						|
		canvas.fillStyle = "rgba(" + color.Rb + "," + color.Gb + "," + color.Bb + "," + color.A + ")";
 | 
						|
		return color;
 | 
						|
	}
 | 
						|
 | 
						|
	override function get_color(): Color {
 | 
						|
		return myColor;
 | 
						|
	}
 | 
						|
 | 
						|
	override function get_imageScaleQuality(): ImageScaleQuality {
 | 
						|
		return scaleQuality;
 | 
						|
	}
 | 
						|
 | 
						|
	override function set_imageScaleQuality(value: ImageScaleQuality): ImageScaleQuality {
 | 
						|
		if (value == ImageScaleQuality.Low) {
 | 
						|
			untyped canvas.mozImageSmoothingEnabled = false;
 | 
						|
			untyped canvas.webkitImageSmoothingEnabled = false;
 | 
						|
			untyped canvas.msImageSmoothingEnabled = false;
 | 
						|
			canvas.imageSmoothingEnabled = false;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			untyped canvas.mozImageSmoothingEnabled = true;
 | 
						|
			untyped canvas.webkitImageSmoothingEnabled = true;
 | 
						|
			untyped canvas.msImageSmoothingEnabled = true;
 | 
						|
			canvas.imageSmoothingEnabled = true;
 | 
						|
		}
 | 
						|
		return scaleQuality = value;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function drawRect(x: Float, y: Float, width: Float, height: Float, strength: Float = 1.0) {
 | 
						|
		canvas.beginPath();
 | 
						|
		var oldStrength = canvas.lineWidth;
 | 
						|
		canvas.lineWidth = Math.round(strength);
 | 
						|
		canvas.rect(x, y, width, height);
 | 
						|
		canvas.stroke();
 | 
						|
		canvas.lineWidth = oldStrength;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function fillRect(x: Float, y: Float, width: Float, height: Float) {
 | 
						|
		canvas.globalAlpha = opacity * myColor.A;
 | 
						|
		canvas.fillRect(x, y, width, height);
 | 
						|
		canvas.globalAlpha = opacity;
 | 
						|
	}
 | 
						|
 | 
						|
	public function drawArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, strength: Float = 1.0, ccw: Bool = false) {
 | 
						|
		_drawArc(cx, cy, radius, sAngle, eAngle, strength, ccw);
 | 
						|
	}
 | 
						|
 | 
						|
	public function drawCircle(cx: Float, cy: Float, radius: Float, strength: Float = 1.0) {
 | 
						|
		_drawArc(cx, cy, radius, 0, 2 * Math.PI, strength, false);
 | 
						|
	}
 | 
						|
 | 
						|
	inline function _drawArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, strength: Float, ccw: Bool) {
 | 
						|
		canvas.beginPath();
 | 
						|
		var oldStrength = canvas.lineWidth;
 | 
						|
		canvas.lineWidth = Math.round(strength);
 | 
						|
		canvas.arc(cx, cy, radius, sAngle, eAngle, ccw);
 | 
						|
		canvas.stroke();
 | 
						|
		canvas.lineWidth = oldStrength;
 | 
						|
	}
 | 
						|
 | 
						|
	public function fillArc(cx: Float, cy: Float, radius: Float, sAngle: Float, eAngle: Float, ccw: Bool = false) {
 | 
						|
		canvas.beginPath();
 | 
						|
		canvas.arc(cx, cy, radius, sAngle, eAngle, ccw);
 | 
						|
		canvas.fill();
 | 
						|
	}
 | 
						|
 | 
						|
	public function fillCircle(cx: Float, cy: Float, radius: Float) {
 | 
						|
		canvas.beginPath();
 | 
						|
		canvas.arc(cx, cy, radius, 0, 2 * Math.PI, false);
 | 
						|
		canvas.fill();
 | 
						|
	}
 | 
						|
 | 
						|
	var bakedQuadCache = new kha.Kravur.AlignedQuad();
 | 
						|
 | 
						|
	override public function drawString(text: String, x: Float, y: Float) {
 | 
						|
		// canvas.fillText(text, tx + x, ty + y + webfont.getHeight());
 | 
						|
		// canvas.drawImage(cast(webfont.getTexture(), Image).image, 0, 0, 50, 50, tx + x, ty + y, 50, 50);
 | 
						|
 | 
						|
		var image = webfont.getImage(fontSize, myColor);
 | 
						|
		if (image.width > 0) {
 | 
						|
			// the image created in getImage() is not imediately useable
 | 
						|
			var xpos = x;
 | 
						|
			var ypos = y;
 | 
						|
			for (i in 0...text.length) {
 | 
						|
				var q = webfont.kravur._get(fontSize).getBakedQuad(bakedQuadCache, kha.graphics2.Graphics.fontGlyphs.indexOf(text.charCodeAt(i)), xpos, ypos);
 | 
						|
 | 
						|
				if (q != null) {
 | 
						|
					if (q.s1 - q.s0 > 0 && q.t1 - q.t0 > 0 && q.x1 - q.x0 > 0 && q.y1 - q.y0 > 0)
 | 
						|
						canvas.drawImage(image, q.s0 * image.width, q.t0 * image.height, (q.s1 - q.s0) * image.width, (q.t1 - q.t0) * image.height, q.x0,
 | 
						|
							q.y0, q.x1 - q.x0, q.y1 - q.y0);
 | 
						|
					xpos += q.xadvance;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	override public function drawCharacters(text: Array<Int>, start: Int, length: Int, x: Float, y: Float): Void {
 | 
						|
		var image = webfont.getImage(fontSize, myColor);
 | 
						|
		if (image.width > 0) {
 | 
						|
			// the image created in getImage() is not imediately useable
 | 
						|
			var xpos = x;
 | 
						|
			var ypos = y;
 | 
						|
			for (i in start...start + length) {
 | 
						|
				var q = webfont.kravur._get(fontSize).getBakedQuad(bakedQuadCache, kha.graphics2.Graphics.fontGlyphs.indexOf(text[i]), xpos, ypos);
 | 
						|
 | 
						|
				if (q != null) {
 | 
						|
					if (q.s1 - q.s0 > 0 && q.t1 - q.t0 > 0 && q.x1 - q.x0 > 0 && q.y1 - q.y0 > 0)
 | 
						|
						canvas.drawImage(image, q.s0 * image.width, q.t0 * image.height, (q.s1 - q.s0) * image.width, (q.t1 - q.t0) * image.height, q.x0,
 | 
						|
							q.y0, q.x1 - q.x0, q.y1 - q.y0);
 | 
						|
					xpos += q.xadvance;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	override function set_font(font: kha.Font): kha.Font {
 | 
						|
		webfont = cast(font, kha.js.Font);
 | 
						|
		// canvas.font = webfont.size + "px " + webfont.name;
 | 
						|
		return cast webfont;
 | 
						|
	}
 | 
						|
 | 
						|
	override function get_font(): kha.Font {
 | 
						|
		return cast webfont;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function drawLine(x1: Float, y1: Float, x2: Float, y2: Float, strength: Float = 1.0) {
 | 
						|
		canvas.beginPath();
 | 
						|
		var oldWith = canvas.lineWidth;
 | 
						|
		canvas.lineWidth = Math.round(strength);
 | 
						|
		canvas.moveTo(x1, y1);
 | 
						|
		canvas.lineTo(x2, y2);
 | 
						|
		canvas.moveTo(0, 0);
 | 
						|
		canvas.stroke();
 | 
						|
		canvas.lineWidth = oldWith;
 | 
						|
	}
 | 
						|
 | 
						|
	override public function fillTriangle(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
 | 
						|
		canvas.beginPath();
 | 
						|
		canvas.moveTo(x1, y1);
 | 
						|
		canvas.lineTo(x2, y2);
 | 
						|
		canvas.lineTo(x3, y3);
 | 
						|
		canvas.closePath();
 | 
						|
		canvas.fill();
 | 
						|
	}
 | 
						|
 | 
						|
	override public function scissor(x: Int, y: Int, width: Int, height: Int): Void {
 | 
						|
		if (!clipping) {
 | 
						|
			canvas.save();
 | 
						|
			clipping = true;
 | 
						|
		}
 | 
						|
		canvas.beginPath();
 | 
						|
		canvas.rect(x, y, width, height);
 | 
						|
		canvas.clip();
 | 
						|
	}
 | 
						|
 | 
						|
	override public function disableScissor(): Void {
 | 
						|
		if (clipping) {
 | 
						|
			canvas.restore();
 | 
						|
			clipping = false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	override public function drawVideo(video: kha.Video, x: Float, y: Float, width: Float, height: Float): Void {
 | 
						|
		canvas.drawImage(cast(video, Video).element, x, y, width, height);
 | 
						|
	}
 | 
						|
 | 
						|
	override public function setTransformation(transformation: FastMatrix3): Void {
 | 
						|
		canvas.setTransform(transformation._00, transformation._01, transformation._10, transformation._11, transformation._20, transformation._21);
 | 
						|
	}
 | 
						|
}
 |