| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 | using System;using System.Drawing;namespace PaintDotNet{    [Serializable]    public unsafe abstract class PixelOp        : IPixelOp    {        public void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, Size roiSize)        {            ApplyBase(dst, dstOffset, src, srcOffset, roiSize);        }        /// <summary>        /// Provides a default implementation for performing dst = F(dst, src) or F(src) over some rectangle         /// of interest. May be slightly faster than calling the other multi-parameter Apply method, as less         /// variables are used in the implementation, thus inducing less register pressure.        /// </summary>        /// <param name="dst">The Surface to write pixels to, and from which pixels are read and used as the lhs parameter for calling the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>.</param>        /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param>        /// <param name="src">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>b>.</param></param>        /// <param name="srcOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the src Surface.</param>        /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param>        public void ApplyBase(Surface dst, Point dstOffset, Surface src, Point srcOffset, Size roiSize)        {            // Create bounding rectangles for each Surface            Rectangle dstRect = new Rectangle(dstOffset, roiSize);            if (dstRect.Width == 0 || dstRect.Height == 0)            {                return;            }            Rectangle srcRect = new Rectangle(srcOffset, roiSize);            if (srcRect.Width == 0 || srcRect.Height == 0)            {                return;            }            // Clip those rectangles to those Surface's bounding rectangles            Rectangle dstClip = Rectangle.Intersect(dstRect, dst.Bounds);            Rectangle srcClip = Rectangle.Intersect(srcRect, src.Bounds);            // If any of those Rectangles actually got clipped, then throw an exception            if (dstRect != dstClip)            {                throw new ArgumentOutOfRangeException                (                    "roiSize",                    "Destination roi out of bounds" +                    ", dst.Size=" + dst.Size.ToString() +                    ", dst.Bounds=" + dst.Bounds.ToString() +                    ", dstOffset=" + dstOffset.ToString() +                    ", src.Size=" + src.Size.ToString() +                    ", srcOffset=" + srcOffset.ToString() +                    ", roiSize=" + roiSize.ToString() +                    ", dstRect=" + dstRect.ToString() +                    ", dstClip=" + dstClip.ToString() +                    ", srcRect=" + srcRect.ToString() +                    ", srcClip=" + srcClip.ToString()                );            }            if (srcRect != srcClip)            {                throw new ArgumentOutOfRangeException("roiSize", "Source roi out of bounds");            }            // Cache the width and height properties            int width = roiSize.Width;            int height = roiSize.Height;            // Do the work.            unsafe            {                for (int row = 0; row < roiSize.Height; ++row)                {                    ColorBgra* dstPtr = dst.GetPointAddress(dstOffset.X, dstOffset.Y + row);                    ColorBgra* srcPtr = src.GetPointAddress(srcOffset.X, srcOffset.Y + row);                    Apply(dstPtr, srcPtr, width);                }            }        }        public virtual void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, int scanLength)        {            Apply(dst.GetPointAddress(dstOffset), src.GetPointAddress(srcOffset), scanLength);        }        public virtual void Apply(ColorBgra* dst, ColorBgra* src, int length)        {            throw new System.NotImplementedException("Derived class must implement Apply(ColorBgra*,ColorBgra*,int)");        }        public PixelOp()        {        }    }}
 |