public void QueueDirtyRegion (Gdk.Rectangle region) { region.Intersect (Allocation); QueueDrawArea (region.X, region.Y, region.Width, region.Height); }
public unsafe static void ExponentialBlur (this DockySurface self, int radius, Gdk.Rectangle area) { if (radius < 1) return; area.Intersect (new Gdk.Rectangle (0, 0, self.Width, self.Height)); int alpha = (int) ((1 << AlphaPrecision) * (1.0 - Math.Exp (-2.3 / (radius + 1.0)))); int height = self.Height; int width = self.Width; ImageSurface original; bool owned; if (self.Internal is ImageSurface) { original = self.Internal as ImageSurface; owned = true; } else { original = new ImageSurface (Format.Argb32, width, height); owned = false; } if (!owned) { using (Cairo.Context cr = new Cairo.Context (original)) { cr.Operator = Operator.Source; cr.SetSource (self.Internal); cr.Paint (); (cr.Target as IDisposable).Dispose (); } } byte* pixels = (byte*) original.DataPtr; // Process Rows Thread th = new Thread ((ThreadStart) delegate { ExponentialBlurRows (pixels, width, height, 0, height / 2, area.X, area.Right, alpha); }); th.Start (); ExponentialBlurRows (pixels, width, height, height / 2, height, area.X, area.Right, alpha); th.Join (); // Process Columns th = new Thread ((ThreadStart) delegate { ExponentialBlurColumns (pixels, width, height, 0, width / 2, area.Y, area.Bottom, alpha); }); th.Start (); ExponentialBlurColumns (pixels, width, height, width / 2, width, area.Y, area.Bottom, alpha); th.Join (); original.MarkDirty (); if (!owned) { self.Context.Operator = Operator.Source; self.Context.SetSource (original); self.Context.Paint (); self.Context.Operator = Operator.Over; (original as IDisposable).Dispose (); original.Destroy (); } }