public static Gdk.Rectangle TransformAndCopy(Gdk.Pixbuf src, Gdk.Pixbuf dest, PixbufOrientation orientation, Gdk.Rectangle args)
    {
        Gdk.Rectangle area = TransformOrientation(src, args, orientation);

        int step = 256;

        Gdk.Rectangle rect = new Gdk.Rectangle(args.X, args.Y,
                                               Math.Min(step, args.Width),
                                               Math.Min(step, args.Height));

        Gdk.Rectangle trect = TransformOrientation(src, rect, orientation);
        Gdk.Pixbuf    tmp   = new Gdk.Pixbuf(src.Colorspace, src.HasAlpha,
                                             src.BitsPerSample,
                                             trect.Width, trect.Height);

        Gdk.Rectangle  subarea;
        BlockProcessor proc = new BlockProcessor(args, 256);

        while (proc.Step(out subarea))
        {
            Gdk.Rectangle trans = TransformOrientation(src, subarea, orientation);
            Gdk.Pixbuf    ssub  = new Gdk.Pixbuf(src, subarea.X, subarea.Y,
                                                 subarea.Width, subarea.Height);

            Gdk.Pixbuf tsub = new Gdk.Pixbuf(tmp, 0, 0, trans.Width, trans.Height);
            CopyWithOrientation(ssub, tsub, orientation);

            tsub.CopyArea(0, 0, trans.Width, trans.Height, dest, trans.X, trans.Y);
            ssub.Dispose();
            tsub.Dispose();
        }

        tmp.Dispose();
        return(area);
    }
        private void OnExpose(Context ctx, Region region)
        {
            SetClip(ctx, region);
            if (Transition != null)
            {
                bool done = false;
                foreach (Gdk.Rectangle area in GetRectangles(region))
                {
                    BlockProcessor proc = new BlockProcessor(area, block_size);
                    Gdk.Rectangle  subarea;
                    while (proc.Step(out subarea))
                    {
                        ctx.Save();
                        SetClip(ctx, subarea);
                        done = !Transition.OnExpose(ctx, Allocation);
                        ctx.Restore();
                    }
                }
                if (done)
                {
                    System.Console.WriteLine("frames = {0}", Transition.Frames);
                    Transition = null;
                }
            }
            else if (effect != null)
            {
                foreach (Gdk.Rectangle area in GetRectangles(region))
                {
                    BlockProcessor proc = new BlockProcessor(area, block_size);
                    Gdk.Rectangle  subarea;
                    while (proc.Step(out subarea))
                    {
                        ctx.Save();
                        SetClip(ctx, subarea);
                        effect.OnExpose(ctx, Allocation);
                        ctx.Restore();
                    }
                }
            }
            else
            {
                ctx.Operator = Operator.Source;
                SurfacePattern p = new SurfacePattern(current.Surface);
                p.Filter = Filter.Fast;
                SetClip(ctx, region);
                ctx.Matrix = current.Fill(Allocation);

                ctx.Source = p;
                ctx.Paint();
                p.Destroy();
            }
        }