<commit_before>package h2d.filter;

private class MaskShader extends h3d.shader.ScreenShader {

	static var SRC = {

		@param var texture : Sampler2D;
		@param var mask : Sampler2D;
		@param var maskMatA : Vec3;
		@param var maskMatB : Vec3;
		@const var smoothAlpha : Bool;

		function fragment() {
			var color = texture.get(input.uv);
			var uv = vec3(input.uv, 1);
			var k = mask.get( vec2(uv.dot(maskMatA), uv.dot(maskMatB)) );
			var alpha = smoothAlpha ? k.a : float(k.a>0);
			output.color = color * alpha;
		}

	};

}


class Mask extends AbstractMask {

	var pass : h3d.pass.ScreenFx<MaskShader>;
	public var smoothAlpha(get, set) : Bool;

	public function new(mask, maskVisible=false, smoothAlpha=false) {
		super(mask);
		pass = new h3d.pass.ScreenFx(new MaskShader());
		this.maskVisible = maskVisible;
		this.smoothAlpha = smoothAlpha;
	}

	function get_smoothAlpha() return pass.shader.smoothAlpha;
	function set_smoothAlpha(v) return pass.shader.smoothAlpha = v;

	override function draw( ctx : RenderContext, t : h2d.Tile ) {
		var mask = getMaskTexture(t);
		if( mask == null )
			throw "Mask should be rendered before masked object";
		var out = ctx.textures.allocTileTarget("maskTmp", t);
		ctx.engine.pushTarget(out);
		pass.shader.texture = t.getTexture();
		pass.shader.mask = getMaskTexture(t);
		pass.shader.maskMatA.set(maskMatrix.a, maskMatrix.c, maskMatrix.x);
		pass.shader.maskMatB.set(maskMatrix.b, maskMatrix.d, maskMatrix.y);
		pass.render();
		ctx.engine.popTarget();
		return h2d.Tile.fromTexture(out);
	}
<commit_msg>fix potential false positive in case mask shape was outside screen<commit_after>package h2d.filter;

private class MaskShader extends h3d.shader.ScreenShader {

	static var SRC = {

		@param var texture : Sampler2D;
		@param var mask : Sampler2D;
		@param var maskMatA : Vec3;
		@param var maskMatB : Vec3;
		@const var smoothAlpha : Bool;

		function fragment() {
			var color = texture.get(input.uv);
			var uv = vec3(input.uv, 1);
			var k = mask.get( vec2(uv.dot(maskMatA), uv.dot(maskMatB)) );
			var alpha = smoothAlpha ? k.a : float(k.a>0);
			output.color = color * alpha;
		}

	};

}


class Mask extends AbstractMask {

	var pass : h3d.pass.ScreenFx<MaskShader>;
	public var smoothAlpha(get, set) : Bool;

	public function new(mask, maskVisible=false, smoothAlpha=false) {
		super(mask);
		pass = new h3d.pass.ScreenFx(new MaskShader());
		this.maskVisible = maskVisible;
		this.smoothAlpha = smoothAlpha;
	}

	function get_smoothAlpha() return pass.shader.smoothAlpha;
	function set_smoothAlpha(v) return pass.shader.smoothAlpha = v;

	override function draw( ctx : RenderContext, t : h2d.Tile ) {
		var mask = getMaskTexture(t);
		if( mask == null ) {
			if( this.mask == null ) throw "Mask filter has no mask object";
			return null;
		}
		var out = ctx.textures.allocTileTarget("maskTmp", t);
		ctx.engine.pushTarget(out);
		pass.shader.texture = t.getTexture();
		pass.shader.mask = getMaskTexture(t);
		pass.shader.maskMatA.set(maskMatrix.a, maskMatrix.c, maskMatrix.x);
		pass.shader.maskMatB.set(maskMatrix.b, maskMatrix.d, maskMatrix.y);
		pass.render();
		ctx.engine.popTarget();
		return h2d.Tile.fromTexture(out);
	}

{'fraction_non_alphanumeric': 0.12840588787973692, 'fraction_numerical': 0.008769182586908864, 'mean_word_length': 4.094098883572568, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4288770', 'n_tokens_mistral': 1211, 'n_tokens_neox': 1116, 'n_words': 268}