<commit_before>/* 
 * SoftFocus.cs
 *
 * Author
 *   <NAME> <<EMAIL>>
 *
 * See COPYING for details.
 */
using Cairo;
using System;

namespace FSpot.Widgets {
	public class SoftFocus : IEffect {
		ImageInfo info;
		double radius;
		double amount;
		Gdk.Point center;
		ImageInfo blur;
		Pattern mask;

		public SoftFocus (ImageInfo info)
		{
			this.info = info;
			center.X = info.Bounds.Width / 2;
			center.Y = info.Bounds.Height / 2;
			Amount = 3;
			Radius = .5;
		}
		
		public Gdk.Point Center {
			get { return center; }
			set { center = value; }
		}
		
		public double Amount {
			get { return amount; }
			set { 
				amount = value; 

				if (blur != null)
					blur.Dispose ();

				blur = CreateBlur (info);
			}
		}
		
		public double Radius {
			get { return radius; }
			set { 
				radius = value; 

				if (blur == null)
					return;
				
				if (mask != null)
					mask.Destroy ();

				mask = CreateMask ();
			}
		}

		private ImageInfo CreateBlur (ImageInfo source)
		{
			double scale = Math.Max (256 / (double) source.Bounds.Width,
						 256 / (double) source.Bounds.Height);

			Gdk.Rectangle small = new Gdk.Rectangle (0, 0,
								(int) Math.Ceiling (source.Bounds.Width * scale),
								(int) Math.Ceiling (source.Bounds.Height * scale));
			
			MemorySurface image = new MemorySurface (Format.Argb32, 
								 small.Width,
								 small.Height);
			
			Context ctx = new Context (image);
			ctx.Matrix = source.Fit (small);
			ctx.Source = new SurfacePattern (source.Surface);
			Console.WriteLine (small);
			ctx.Paint ();
			((IDisposable)ctx).Dispose ();
			Gdk.Pixbuf normal = CairoUtils.CreatePixbuf (image);
			Gdk.Pixbuf blur = PixbufUtils.Blur (normal, 3);
			ImageInfo overlay = new ImageInfo (blur);
			blur.Dispose ();
			normal.Dispose ();
			return overlay;
		}
		
		private Pattern CreateMask ()
		{
			double max = Math.Max (blur.Bounds.Width, blur.Bounds.Height) * .25;
			double scale = blur.Bounds.Width / (double) info.Bounds.Width;

			RadialGradient circle = new RadialGradient (center.X * scale, center.Y * scale, radius * max,
								    center.X * scale, center.Y * scale, radius * max * .7);
			circle.AddColorStop (0, new Cairo.Color (0.0, 0.0, 0.0, 0.0));
			circle.AddColorStop (1.0, new Cairo.Color (1.0, 1.0, 1.0, 1.0));
			return circle;
		}
		
		public bool OnExpose (Context ctx, Gdk.Rectangle allocation)
		{
			SurfacePattern p = new SurfacePattern (info.Surface);
			ctx.Matrix = new Matrix ();
			Matrix m = info.Fit (allocation);
			ctx.Operator = Operator.Over;
			ctx.Matrix = m;
			ctx.Source = p;
			ctx.Paint ();

			SurfacePattern overlay = new SurfacePattern (blur.Surface);
			ctx.Matrix = new Matrix ();
			ctx.Matrix = blur.Fit (allocation);
			ctx.Operator = Operator.Over;
			ctx.Source = overlay;
			
			// FIXME ouch this is ugly.
			if (mask == null)
				Radius = Radius;

			ctx.Paint ();
			//ctx.Mask (mask);
			overlay.Destroy ();
			p.Destroy ();
			return true;<commit_msg>Fix the effect by actually applng the mask.<commit_after>/* 
 * SoftFocus.cs
 *
 * Author
 *   <NAME> <<EMAIL>>
 *
 * See COPYING for details.
 */
using Cairo;
using System;

namespace FSpot.Widgets {
	public class SoftFocus : IEffect {
		ImageInfo info;
		double radius;
		double amount;
		Gdk.Point center;
		ImageInfo blur;
		Pattern mask;

		public SoftFocus (ImageInfo info)
		{
			this.info = info;
			center.X = info.Bounds.Width / 2;
			center.Y = info.Bounds.Height / 2;
			Amount = 3;
			Radius = .5;
		}
		
		public Gdk.Point Center {
			get { return center; }
			set { center = value; }
		}
		
		public double Amount {
			get { return amount; }
			set { 
				amount = value; 

				if (blur != null)
					blur.Dispose ();

				blur = CreateBlur (info);
			}
		}
		
		public double Radius {
			get { return radius; }
			set { 
				radius = value; 

				if (blur == null)
					return;
				
				if (mask != null)
					mask.Destroy ();

				mask = CreateMask ();
			}
		}

		private ImageInfo CreateBlur (ImageInfo source)
		{
			double scale = Math.Max (256 / (double) source.Bounds.Width,
						 256 / (double) source.Bounds.Height);

			Gdk.Rectangle small = new Gdk.Rectangle (0, 0,
								(int) Math.Ceiling (source.Bounds.Width * scale),
								(int) Math.Ceiling (source.Bounds.Height * scale));
			
			MemorySurface image = new MemorySurface (Format.Argb32, 
								 small.Width,
								 small.Height);
			
			Context ctx = new Context (image);
			ctx.Matrix = source.Fit (small);
			ctx.Source = new SurfacePattern (source.Surface);
			Console.WriteLine (small);
			ctx.Paint ();
			((IDisposable)ctx).Dispose ();
			Gdk.Pixbuf normal = CairoUtils.CreatePixbuf (image);
			Gdk.Pixbuf blur = PixbufUtils.Blur (normal, 3);
			ImageInfo overlay = new ImageInfo (blur);
			blur.Dispose ();
			normal.Dispose ();
			return overlay;
		}
		
		private Pattern CreateMask ()
		{
			double max = Math.Max (blur.Bounds.Width, blur.Bounds.Height) * .25;
			double scale = blur.Bounds.Width / (double) info.Bounds.Width;

			RadialGradient circle = new RadialGradient (center.X * scale, center.Y * scale, radius * max,
								    center.X * scale, center.Y * scale, radius * max * .7);
			circle.AddColorStop (0, new Cairo.Color (0.0, 0.0, 0.0, 0.0));
			circle.AddColorStop (1.0, new Cairo.Color (1.0, 1.0, 1.0, 1.0));
			return circle;
		}
		
		public bool OnExpose (Context ctx, Gdk.Rectangle allocation)
		{
			SurfacePattern p = new SurfacePattern (info.Surface);
			ctx.Matrix = new Matrix ();
			Matrix m = info.Fit (allocation);
			ctx.Operator = Operator.Over;
			ctx.Matrix = m;
			ctx.Source = p;
			ctx.Paint ();

			SurfacePattern overlay = new SurfacePattern (blur.Surface);
			ctx.Matrix = new Matrix ();
			ctx.Matrix = blur.Fit (allocation);
			ctx.Operator = Operator.Over;
			ctx.Source = overlay;
			
			// FIXME ouch this is ugly.
			if (mask == null)
				Radius = Radius;

			//ctx.Paint ();
			ctx.Mask (mask);
			overlay.Destroy ();
			p.Destroy ();
			return true;
{'fraction_non_alphanumeric': 0.13095238095238096, 'fraction_numerical': 0.012407780013413815, 'mean_word_length': 2.544266191325015, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '1648456', 'n_tokens_mistral': 2541, 'n_tokens_neox': 1941, 'n_words': 540}